blob: 74e4bc53304f601f7e03345d3caebca1157ca5db [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 Vishniakouf372b812023-02-14 18:06:51 -080061static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
62static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
63static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
64static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
65static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080066static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080067static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080068/**
69 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
70 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
71 * index 0) is the new pointer going down. The same pointer could have been placed at a different
72 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
73 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
74 * pointer id=0 leaves but the pointer id=1 remains.
75 */
76static constexpr int32_t POINTER_0_DOWN =
77 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080078static constexpr int32_t POINTER_1_DOWN =
79 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000080static constexpr int32_t POINTER_2_DOWN =
81 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000082static constexpr int32_t POINTER_3_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000084static constexpr int32_t POINTER_0_UP =
85 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080086static constexpr int32_t POINTER_1_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88
Antonio Kantek15beb512022-06-13 22:35:41 +000089// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000090static constexpr int32_t WINDOW_PID = 999;
91static constexpr int32_t WINDOW_UID = 1001;
92
Antonio Kantek15beb512022-06-13 22:35:41 +000093// The default pid and uid for the windows created on the secondary display by the test.
94static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
95static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
96
Prabir Pradhan5735a322022-04-11 17:23:34 +000097// The default policy flags to use for event injection by tests.
98static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080099
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000100// An arbitrary pid of the gesture monitor window
101static constexpr int32_t MONITOR_PID = 2001;
102
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800103static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
104
Arthur Hungc539dbb2022-12-08 07:45:36 +0000105static constexpr int expectedWallpaperFlags =
106 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
107
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800108using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
109
chaviwd1c23182019-12-20 18:44:56 -0800110struct PointF {
111 float x;
112 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800113 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800114};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800115
Gang Wang342c9272020-01-13 13:15:04 -0500116/**
117 * Return a DOWN key event with KEYCODE_A.
118 */
119static KeyEvent getTestKeyEvent() {
120 KeyEvent event;
121
Garfield Tanfbe732e2020-01-24 11:26:14 -0800122 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
123 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
124 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500125 return event;
126}
127
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000128static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
129 ASSERT_EQ(expectedAction, receivedAction)
130 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
131 << MotionEvent::actionToString(receivedAction);
132}
133
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800134MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
135 bool matches = action == arg.getAction();
136 if (!matches) {
137 *result_listener << "expected action " << MotionEvent::actionToString(action)
138 << ", but got " << MotionEvent::actionToString(arg.getAction());
139 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800140 if (action == AMOTION_EVENT_ACTION_DOWN) {
141 if (!matches) {
142 *result_listener << "; ";
143 }
144 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
145 matches &= arg.getDownTime() == arg.getEventTime();
146 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800147 if (action == AMOTION_EVENT_ACTION_CANCEL) {
148 if (!matches) {
149 *result_listener << "; ";
150 }
151 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
152 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
153 }
154 return matches;
155}
156
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800157MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
158 return arg.getDownTime() == downTime;
159}
160
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800161MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
162 return arg.getDisplayId() == displayId;
163}
164
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800165MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
166 return arg.getDeviceId() == deviceId;
167}
168
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800169MATCHER_P(WithSource, source, "InputEvent with specified source") {
170 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
171 << inputEventSourceToString(arg.getSource());
172 return arg.getSource() == source;
173}
174
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800175MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
176 return arg.getFlags() == flags;
177}
178
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800179MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
180 if (arg.getPointerCount() != 1) {
181 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
182 return false;
183 }
Harry Cutts33476232023-01-30 19:57:29 +0000184 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800185}
186
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800187MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
188 return arg.getPointerCount() == pointerCount;
189}
190
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800191MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
192 // Build a map for the received pointers, by pointer id
193 std::map<int32_t /*pointerId*/, PointF> actualPointers;
194 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
195 const int32_t pointerId = arg.getPointerId(pointerIndex);
196 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
197 }
198 return pointers == actualPointers;
199}
200
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201// --- FakeInputDispatcherPolicy ---
202
203class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
204 InputDispatcherConfiguration mConfig;
205
Prabir Pradhanedd96402022-02-15 01:46:16 -0800206 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
207
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000209 FakeInputDispatcherPolicy() = default;
210 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800211
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800212 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700213 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700214 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700215 EXPECT_EQ(event.getDisplayId(), args.displayId);
216
217 const auto& keyEvent = static_cast<const KeyEvent&>(event);
218 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
219 EXPECT_EQ(keyEvent.getAction(), args.action);
220 });
Jackal Guof9696682018-10-05 12:23:23 +0800221 }
222
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700223 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
224 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700225 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700226 EXPECT_EQ(event.getDisplayId(), args.displayId);
227
228 const auto& motionEvent = static_cast<const MotionEvent&>(event);
229 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
230 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000231 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
232 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
233 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
234 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700235 });
Jackal Guof9696682018-10-05 12:23:23 +0800236 }
237
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700238 void assertFilterInputEventWasNotCalled() {
239 std::scoped_lock lock(mLock);
240 ASSERT_EQ(nullptr, mFilteredEvent);
241 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800243 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700244 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800245 ASSERT_TRUE(mConfigurationChangedTime)
246 << "Timed out waiting for configuration changed call";
247 ASSERT_EQ(*mConfigurationChangedTime, when);
248 mConfigurationChangedTime = std::nullopt;
249 }
250
251 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700252 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800254 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
256 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
257 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
258 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
259 mLastNotifySwitch = std::nullopt;
260 }
261
chaviwfd6d3512019-03-25 13:23:49 -0700262 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700263 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800264 ASSERT_EQ(touchedToken, mOnPointerDownToken);
265 mOnPointerDownToken.clear();
266 }
267
268 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_TRUE(mOnPointerDownToken == nullptr)
271 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700272 }
273
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700274 // This function must be called soon after the expected ANR timer starts,
275 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500276 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700277 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500278 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 std::unique_lock lock(mLock);
280 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 ASSERT_NO_FATAL_FAILURE(
283 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000287 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 const sp<WindowInfoHandle>& window) {
289 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
290 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
291 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 }
293
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
295 const sp<IBinder>& expectedToken,
296 int32_t expectedPid) {
297 std::unique_lock lock(mLock);
298 android::base::ScopedLockAssertion assumeLocked(mLock);
299 AnrResult result;
300 ASSERT_NO_FATAL_FAILURE(result =
301 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
302 const auto& [token, pid] = result;
303 ASSERT_EQ(expectedToken, token);
304 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500305 }
306
Prabir Pradhanedd96402022-02-15 01:46:16 -0800307 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000308 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 std::unique_lock lock(mLock);
310 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
312 const auto& [token, _] = result;
313 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000314 }
315
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
317 int32_t expectedPid) {
318 std::unique_lock lock(mLock);
319 android::base::ScopedLockAssertion assumeLocked(mLock);
320 AnrResult result;
321 ASSERT_NO_FATAL_FAILURE(
322 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
323 const auto& [token, pid] = result;
324 ASSERT_EQ(expectedToken, token);
325 ASSERT_EQ(expectedPid, pid);
326 }
327
328 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000329 sp<IBinder> getResponsiveWindowToken() {
330 std::unique_lock lock(mLock);
331 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800332 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
333 const auto& [token, _] = result;
334 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700335 }
336
337 void assertNotifyAnrWasNotCalled() {
338 std::scoped_lock lock(mLock);
339 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800340 ASSERT_TRUE(mAnrWindows.empty());
341 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500342 << "ANR was not called, but please also consume the 'connection is responsive' "
343 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700344 }
345
Garfield Tan1c7bc862020-01-28 13:24:04 -0800346 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
347 mConfig.keyRepeatTimeout = timeout;
348 mConfig.keyRepeatDelay = delay;
349 }
350
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000351 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800352 std::unique_lock lock(mLock);
353 base::ScopedLockAssertion assumeLocked(mLock);
354
355 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
356 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800358 enabled;
359 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
361 << ") to be called.";
362 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000364 auto request = *mPointerCaptureRequest;
365 mPointerCaptureRequest.reset();
366 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800367 }
368
369 void assertSetPointerCaptureNotCalled() {
370 std::unique_lock lock(mLock);
371 base::ScopedLockAssertion assumeLocked(mLock);
372
373 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
380
arthurhungf452d0b2021-01-06 00:19:52 +0800381 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
382 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800384 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800386 }
387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800388 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391 std::optional<sp<IBinder>> receivedToken =
392 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
393 mNotifyInputChannelBroken);
394 ASSERT_TRUE(receivedToken.has_value());
395 ASSERT_EQ(token, *receivedToken);
396 }
397
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800398 /**
399 * Set policy timeout. A value of zero means next key will not be intercepted.
400 */
401 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
402 mInterceptKeyTimeout = timeout;
403 }
404
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700406 std::mutex mLock;
407 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
408 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
409 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
410 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800411
Prabir Pradhan99987712020-11-10 18:43:05 -0800412 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000413
414 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800415
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700416 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700417 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800418 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
419 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700420 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800421 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
422 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700423
arthurhungf452d0b2021-01-06 00:19:52 +0800424 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800425 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800426
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800427 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
471 ADD_FAILURE() << "Did not receive the expected callback";
472 return std::nullopt;
473 }
474 T item = storage.front();
475 storage.pop();
476 return std::make_optional(item);
477 }
478
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600479 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700480 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800481 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 }
483
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
485 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700486 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800487 ASSERT_TRUE(pid.has_value());
488 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700489 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500490 }
491
Prabir Pradhanedd96402022-02-15 01:46:16 -0800492 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
493 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500494 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800495 ASSERT_TRUE(pid.has_value());
496 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500497 mNotifyAnr.notify_all();
498 }
499
500 void notifyNoFocusedWindowAnr(
501 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
502 std::scoped_lock lock(mLock);
503 mAnrApplications.push(applicationHandle);
504 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 }
506
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800507 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
508 std::scoped_lock lock(mLock);
509 mBrokenInputChannels.push(connectionToken);
510 mNotifyInputChannelBroken.notify_all();
511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600513 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700514
Chris Yef59a2f42020-10-16 12:55:26 -0700515 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
516 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
517 const std::vector<float>& values) override {}
518
519 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
520 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000521
Chris Yefb552902021-02-03 17:18:37 -0800522 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
523
Prabir Pradhana41d2442023-04-20 21:30:40 +0000524 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525
Prabir Pradhana41d2442023-04-20 21:30:40 +0000526 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700527 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000528 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700529 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000530 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
531 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800532 break;
533 }
534
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700535 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000536 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
537 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800538 break;
539 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700540 default: {
541 ADD_FAILURE() << "Should only filter keys or motions";
542 break;
543 }
Jackal Guof9696682018-10-05 12:23:23 +0800544 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800545 return true;
546 }
547
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
549 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800550 // Clear intercept state when we handled the event.
551 mInterceptKeyTimeout = 0ms;
552 }
553 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600555 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556
Prabir Pradhana41d2442023-04-20 21:30:40 +0000557 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800558 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
559 // Clear intercept state so we could dispatch the event in next wake.
560 mInterceptKeyTimeout = 0ms;
561 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800562 }
563
Prabir Pradhana41d2442023-04-20 21:30:40 +0000564 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
565 uint32_t) override {
566 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600569 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
570 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700571 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800572 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
573 * essentially a passthrough for notifySwitch.
574 */
Harry Cutts33476232023-01-30 19:57:29 +0000575 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576 }
577
Sean Stoutb4e0a592021-02-23 07:34:53 -0800578 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600580 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700581 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700582 mOnPointerDownToken = newToken;
583 }
584
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000585 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800586 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000587 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800588 mPointerCaptureChangedCondition.notify_all();
589 }
590
arthurhungf452d0b2021-01-06 00:19:52 +0800591 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
592 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800593 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800594 mDropTargetWindowToken = token;
595 }
596
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700597 void assertFilterInputEventWasCalledInternal(
598 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700599 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800600 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700601 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800602 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800603 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800604};
605
Michael Wrightd02c5b62014-02-10 15:10:22 -0800606// --- InputDispatcherTest ---
607
608class InputDispatcherTest : public testing::Test {
609protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000610 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700611 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800612
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000613 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000614 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
615 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800616 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000617 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700618 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800619 }
620
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000621 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700622 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000623 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700624 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800625 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700626
627 /**
628 * Used for debugging when writing the test
629 */
630 void dumpDispatcherState() {
631 std::string dump;
632 mDispatcher->dump(dump);
633 std::stringstream ss(dump);
634 std::string to;
635
636 while (std::getline(ss, to, '\n')) {
637 ALOGE("%s", to.c_str());
638 }
639 }
Vishnu Nair958da932020-08-21 17:12:37 -0700640
Chavi Weingarten847e8512023-03-29 00:26:09 +0000641 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700642 FocusRequest request;
643 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000644 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700645 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
646 request.displayId = window->getInfo()->displayId;
647 mDispatcher->setFocusedWindow(request);
648 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649};
650
Michael Wrightd02c5b62014-02-10 15:10:22 -0800651TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
652 KeyEvent event;
653
654 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800655 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
656 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600657 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
658 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800659 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000660 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000661 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662 << "Should reject key events with undefined action.";
663
664 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800665 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
666 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600667 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800668 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000669 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000670 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800671 << "Should reject key events with ACTION_MULTIPLE.";
672}
673
674TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
675 MotionEvent event;
676 PointerProperties pointerProperties[MAX_POINTERS + 1];
677 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800678 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679 pointerProperties[i].clear();
680 pointerProperties[i].id = i;
681 pointerCoords[i].clear();
682 }
683
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800684 // Some constants commonly used below
685 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
686 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
687 constexpr int32_t metaState = AMETA_NONE;
688 constexpr MotionClassification classification = MotionClassification::NONE;
689
chaviw9eaa22c2020-07-01 16:21:27 -0700690 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800691 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800692 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700693 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
694 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700695 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
696 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700697 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800698 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000699 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000700 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800701 << "Should reject motion events with undefined action.";
702
703 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800704 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800705 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
706 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
707 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
708 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500709 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800710 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000711 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000712 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713 << "Should reject motion events with pointer down index too large.";
714
Garfield Tanfbe732e2020-01-24 11:26:14 -0800715 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700716 AMOTION_EVENT_ACTION_POINTER_DOWN |
717 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700718 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
719 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700720 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500721 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800722 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000723 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000724 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800725 << "Should reject motion events with pointer down index too small.";
726
727 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800728 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800729 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
730 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
731 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
732 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500733 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800734 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000735 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000736 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800737 << "Should reject motion events with pointer up index too large.";
738
Garfield Tanfbe732e2020-01-24 11:26:14 -0800739 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700740 AMOTION_EVENT_ACTION_POINTER_UP |
741 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700742 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
743 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700744 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500745 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800746 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000747 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000748 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800749 << "Should reject motion events with pointer up index too small.";
750
751 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800752 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
753 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700754 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700755 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
756 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700757 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800758 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000759 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000760 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800761 << "Should reject motion events with 0 pointers.";
762
Garfield Tanfbe732e2020-01-24 11:26:14 -0800763 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
764 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700765 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700766 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
767 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700768 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800769 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000770 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000771 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800772 << "Should reject motion events with more than MAX_POINTERS pointers.";
773
774 // Rejects motion events with invalid pointer ids.
775 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800776 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
777 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700778 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700779 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
780 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700781 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000784 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 << "Should reject motion events with pointer ids less than 0.";
786
787 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800788 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
789 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700790 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700791 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
792 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700793 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000795 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000796 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
798
799 // Rejects motion events with duplicate pointer ids.
800 pointerProperties[0].id = 1;
801 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800802 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
803 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700804 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700805 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
806 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700807 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800808 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000809 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000810 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800811 << "Should reject motion events with duplicate pointer ids.";
812}
813
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800814/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
815
816TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
817 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000818 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800819 ASSERT_TRUE(mDispatcher->waitForIdle());
820
821 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
822}
823
824TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000825 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
826 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000827 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800828
829 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
830 args.policyFlags |= POLICY_FLAG_TRUSTED;
831 mFakePolicy->assertNotifySwitchWasCalled(args);
832}
833
Arthur Hungb92218b2018-08-14 12:00:21 +0800834// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700835static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700836// Default input dispatching timeout if there is no focused application or paused window
837// from which to determine an appropriate dispatching timeout.
838static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
839 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
840 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800841
842class FakeApplicationHandle : public InputApplicationHandle {
843public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700844 FakeApplicationHandle() {
845 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700846 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500847 mInfo.dispatchingTimeoutMillis =
848 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700849 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800850 virtual ~FakeApplicationHandle() {}
851
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000852 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700853
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500854 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
855 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700856 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800857};
858
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800859class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800860public:
Garfield Tan15601662020-09-22 15:32:38 -0700861 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800862 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700863 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800864 }
865
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800866 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867 InputEvent* event;
868 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
869 if (!consumeSeq) {
870 return nullptr;
871 }
872 finishEvent(*consumeSeq);
873 return event;
874 }
875
876 /**
877 * Receive an event without acknowledging it.
878 * Return the sequence number that could later be used to send finished signal.
879 */
880 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800881 uint32_t consumeSeq;
882 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800883
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800884 std::chrono::time_point start = std::chrono::steady_clock::now();
885 status_t status = WOULD_BLOCK;
886 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000887 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 &event);
889 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
890 if (elapsed > 100ms) {
891 break;
892 }
893 }
894
895 if (status == WOULD_BLOCK) {
896 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800898 }
899
900 if (status != OK) {
901 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700902 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 }
904 if (event == nullptr) {
905 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700906 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800907 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700908 if (outEvent != nullptr) {
909 *outEvent = event;
910 }
911 return consumeSeq;
912 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800913
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 /**
915 * To be used together with "receiveEvent" to complete the consumption of an event.
916 */
917 void finishEvent(uint32_t consumeSeq) {
918 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
919 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 }
921
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000922 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
923 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
924 ASSERT_EQ(OK, status);
925 }
926
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700927 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000928 std::optional<int32_t> expectedDisplayId,
929 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 InputEvent* event = consume();
931
932 ASSERT_NE(nullptr, event) << mName.c_str()
933 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800934 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700935 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
936 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800937
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000938 if (expectedDisplayId.has_value()) {
939 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
940 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800941
Tiger Huang8664f8c2018-10-11 19:14:35 +0800942 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700943 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800944 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
945 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000946 if (expectedFlags.has_value()) {
947 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
948 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800949 break;
950 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700951 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800952 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000953 assertMotionAction(expectedAction, motionEvent.getAction());
954
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000955 if (expectedFlags.has_value()) {
956 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
957 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800958 break;
959 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700960 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100961 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
962 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700963 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800964 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
965 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700966 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000967 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
968 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700969 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800970 FAIL() << "Use 'consumeDragEvent' for DRAG events";
971 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800973 }
974
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800975 MotionEvent* consumeMotion() {
976 InputEvent* event = consume();
977
978 if (event == nullptr) {
979 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
980 return nullptr;
981 }
982
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 if (event->getType() != InputEventType::MOTION) {
984 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800985 return nullptr;
986 }
987 return static_cast<MotionEvent*>(event);
988 }
989
990 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
991 MotionEvent* motionEvent = consumeMotion();
992 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
993 ASSERT_THAT(*motionEvent, matcher);
994 }
995
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100996 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
997 InputEvent* event = consume();
998 ASSERT_NE(nullptr, event) << mName.c_str()
999 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1001 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001002
1003 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1004 << mName.c_str() << ": event displayId should always be NONE.";
1005
1006 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1007 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001008 }
1009
Prabir Pradhan99987712020-11-10 18:43:05 -08001010 void consumeCaptureEvent(bool hasCapture) {
1011 const InputEvent* event = consume();
1012 ASSERT_NE(nullptr, event) << mName.c_str()
1013 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001014 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1015 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001016
1017 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1018 << mName.c_str() << ": event displayId should always be NONE.";
1019
1020 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1021 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1022 }
1023
arthurhungb89ccb02020-12-30 16:19:01 +08001024 void consumeDragEvent(bool isExiting, float x, float y) {
1025 const InputEvent* event = consume();
1026 ASSERT_NE(nullptr, event) << mName.c_str()
1027 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001028 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001029
1030 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1031 << mName.c_str() << ": event displayId should always be NONE.";
1032
1033 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1034 EXPECT_EQ(isExiting, dragEvent.isExiting());
1035 EXPECT_EQ(x, dragEvent.getX());
1036 EXPECT_EQ(y, dragEvent.getY());
1037 }
1038
Antonio Kantekf16f2832021-09-28 04:39:20 +00001039 void consumeTouchModeEvent(bool inTouchMode) {
1040 const InputEvent* event = consume();
1041 ASSERT_NE(nullptr, event) << mName.c_str()
1042 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001043 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1044 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001045
1046 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1047 << mName.c_str() << ": event displayId should always be NONE.";
1048 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1049 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1050 }
1051
chaviwd1c23182019-12-20 18:44:56 -08001052 void assertNoEvents() {
1053 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001054 if (event == nullptr) {
1055 return;
1056 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001058 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1059 ADD_FAILURE() << "Received key event "
1060 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1063 ADD_FAILURE() << "Received motion event "
1064 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001066 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1067 ADD_FAILURE() << "Received focus event, hasFocus = "
1068 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001070 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1071 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1072 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001074 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1075 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1076 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001077 }
1078 FAIL() << mName.c_str()
1079 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001080 }
1081
1082 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1083
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001084 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1085
chaviwd1c23182019-12-20 18:44:56 -08001086protected:
1087 std::unique_ptr<InputConsumer> mConsumer;
1088 PreallocatedInputEventFactory mEventFactory;
1089
1090 std::string mName;
1091};
1092
chaviw3277faf2021-05-19 16:45:23 -05001093class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001094public:
1095 static const int32_t WIDTH = 600;
1096 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001097
Chris Yea209fde2020-07-22 13:54:51 -07001098 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001099 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001100 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001101 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001102 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001103 base::Result<std::unique_ptr<InputChannel>> channel =
1104 dispatcher->createInputChannel(name);
1105 token = (*channel)->getConnectionToken();
1106 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001107 }
1108
1109 inputApplicationHandle->updateInfo();
1110 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1111
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001112 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001113 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001114 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001115 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001116 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001117 mInfo.frameLeft = 0;
1118 mInfo.frameTop = 0;
1119 mInfo.frameRight = WIDTH;
1120 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001121 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001122 mInfo.globalScaleFactor = 1.0;
1123 mInfo.touchableRegion.clear();
1124 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001125 mInfo.ownerPid = WINDOW_PID;
1126 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001127 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001128 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001129 }
1130
Arthur Hungabbb9d82021-09-01 14:52:30 +00001131 sp<FakeWindowHandle> clone(
1132 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001133 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001134 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001135 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1136 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001137 return handle;
1138 }
1139
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001140 void setTouchable(bool touchable) {
1141 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1142 }
chaviwd1c23182019-12-20 18:44:56 -08001143
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001144 void setFocusable(bool focusable) {
1145 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1146 }
1147
1148 void setVisible(bool visible) {
1149 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1150 }
Vishnu Nair958da932020-08-21 17:12:37 -07001151
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001152 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001153 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001154 }
1155
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001156 void setPaused(bool paused) {
1157 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1158 }
1159
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001160 void setPreventSplitting(bool preventSplitting) {
1161 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001162 }
1163
1164 void setSlippery(bool slippery) {
1165 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1166 }
1167
1168 void setWatchOutsideTouch(bool watchOutside) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1170 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001171
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001172 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1173
1174 void setInterceptsStylus(bool interceptsStylus) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1176 }
1177
1178 void setDropInput(bool dropInput) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1180 }
1181
1182 void setDropInputIfObscured(bool dropInputIfObscured) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1184 }
1185
1186 void setNoInputChannel(bool noInputChannel) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1188 }
1189
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001190 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1191
chaviw3277faf2021-05-19 16:45:23 -05001192 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001193
Bernardo Rufino7393d172021-02-26 13:56:11 +00001194 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1195
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001196 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001197 mInfo.frameLeft = frame.left;
1198 mInfo.frameTop = frame.top;
1199 mInfo.frameRight = frame.right;
1200 mInfo.frameBottom = frame.bottom;
1201 mInfo.touchableRegion.clear();
1202 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001203
1204 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1205 ui::Transform translate;
1206 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1207 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001208 }
1209
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001210 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setIsWallpaper(bool isWallpaper) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1214 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setDupTouchToWallpaper(bool hasWallpaper) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1218 }
chaviwd1c23182019-12-20 18:44:56 -08001219
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001220 void setTrustedOverlay(bool trustedOverlay) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1222 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001223
chaviw9eaa22c2020-07-01 16:21:27 -07001224 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1225 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1226 }
1227
1228 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001229
yunho.shinf4a80b82020-11-16 21:13:57 +09001230 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1231
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001232 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001233 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001234 }
1235
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001236 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001237 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001238 }
1239
Svet Ganov5d3bc372020-01-26 23:11:07 -08001240 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001241 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001242 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1243 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001244 }
1245
1246 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001247 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001248 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1249 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001250 }
1251
1252 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001253 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001254 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1255 }
1256
1257 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1258 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001259 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001260 expectedFlags);
1261 }
1262
Svet Ganov5d3bc372020-01-26 23:11:07 -08001263 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001264 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1265 int32_t expectedFlags = 0) {
1266 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1267 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001268 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001269 }
1270
1271 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001272 int32_t expectedFlags = 0) {
1273 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1274 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001275 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001276 }
1277
1278 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001279 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001280 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001281 expectedFlags);
1282 }
1283
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001284 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1285 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001287 expectedFlags);
1288 }
1289
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001290 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1291 int32_t expectedFlags = 0) {
1292 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001293 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001294 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001295 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1296 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1297 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1298 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1299 }
1300
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001301 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1302 ASSERT_NE(mInputReceiver, nullptr)
1303 << "Cannot consume events from a window with no receiver";
1304 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1305 }
1306
Prabir Pradhan99987712020-11-10 18:43:05 -08001307 void consumeCaptureEvent(bool hasCapture) {
1308 ASSERT_NE(mInputReceiver, nullptr)
1309 << "Cannot consume events from a window with no receiver";
1310 mInputReceiver->consumeCaptureEvent(hasCapture);
1311 }
1312
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001313 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1314 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001315 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001316 ASSERT_THAT(*motionEvent, matcher);
1317 }
1318
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001319 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001320 std::optional<int32_t> expectedDisplayId,
1321 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001322 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1323 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1324 expectedFlags);
1325 }
1326
arthurhungb89ccb02020-12-30 16:19:01 +08001327 void consumeDragEvent(bool isExiting, float x, float y) {
1328 mInputReceiver->consumeDragEvent(isExiting, x, y);
1329 }
1330
Antonio Kantekf16f2832021-09-28 04:39:20 +00001331 void consumeTouchModeEvent(bool inTouchMode) {
1332 ASSERT_NE(mInputReceiver, nullptr)
1333 << "Cannot consume events from a window with no receiver";
1334 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1335 }
1336
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001337 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001338 if (mInputReceiver == nullptr) {
1339 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1340 return std::nullopt;
1341 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001342 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001343 }
1344
1345 void finishEvent(uint32_t sequenceNum) {
1346 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1347 mInputReceiver->finishEvent(sequenceNum);
1348 }
1349
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001350 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1351 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1352 mInputReceiver->sendTimeline(inputEventId, timeline);
1353 }
1354
chaviwaf87b3e2019-10-01 16:59:28 -07001355 InputEvent* consume() {
1356 if (mInputReceiver == nullptr) {
1357 return nullptr;
1358 }
1359 return mInputReceiver->consume();
1360 }
1361
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001362 MotionEvent* consumeMotion() {
1363 InputEvent* event = consume();
1364 if (event == nullptr) {
1365 ADD_FAILURE() << "Consume failed : no event";
1366 return nullptr;
1367 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001368 if (event->getType() != InputEventType::MOTION) {
1369 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001370 return nullptr;
1371 }
1372 return static_cast<MotionEvent*>(event);
1373 }
1374
Arthur Hungb92218b2018-08-14 12:00:21 +08001375 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001376 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001377 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001378 return; // Can't receive events if the window does not have input channel
1379 }
1380 ASSERT_NE(nullptr, mInputReceiver)
1381 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001382 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001383 }
1384
chaviwaf87b3e2019-10-01 16:59:28 -07001385 sp<IBinder> getToken() { return mInfo.token; }
1386
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001387 const std::string& getName() { return mName; }
1388
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001389 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1390 mInfo.ownerPid = ownerPid;
1391 mInfo.ownerUid = ownerUid;
1392 }
1393
Prabir Pradhanedd96402022-02-15 01:46:16 -08001394 int32_t getPid() const { return mInfo.ownerPid; }
1395
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001396 void destroyReceiver() { mInputReceiver = nullptr; }
1397
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001398 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1399
chaviwd1c23182019-12-20 18:44:56 -08001400private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001401 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001402 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001403 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001404};
1405
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001406std::atomic<int32_t> FakeWindowHandle::sId{1};
1407
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001408static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001409 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001410 int32_t displayId = ADISPLAY_ID_NONE,
1411 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001412 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001413 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1414 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001415 KeyEvent event;
1416 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1417
1418 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001419 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001420 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1421 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001422
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001423 if (!allowKeyRepeat) {
1424 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1425 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001426 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001427 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001428}
1429
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001430static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001431 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001432 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001433}
1434
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001435// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1436// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1437// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001438static InputEventInjectionResult injectKeyDownNoRepeat(
1439 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001440 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001441 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001442 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001443}
1444
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001445static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001446 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001447 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001448}
1449
Garfield Tandf26e862020-07-01 20:18:19 -07001450class PointerBuilder {
1451public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001452 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001453 mProperties.clear();
1454 mProperties.id = id;
1455 mProperties.toolType = toolType;
1456 mCoords.clear();
1457 }
1458
1459 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1460
1461 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1462
1463 PointerBuilder& axis(int32_t axis, float value) {
1464 mCoords.setAxisValue(axis, value);
1465 return *this;
1466 }
1467
1468 PointerProperties buildProperties() const { return mProperties; }
1469
1470 PointerCoords buildCoords() const { return mCoords; }
1471
1472private:
1473 PointerProperties mProperties;
1474 PointerCoords mCoords;
1475};
1476
1477class MotionEventBuilder {
1478public:
1479 MotionEventBuilder(int32_t action, int32_t source) {
1480 mAction = action;
1481 mSource = source;
1482 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001483 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001484 }
1485
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001486 MotionEventBuilder& deviceId(int32_t deviceId) {
1487 mDeviceId = deviceId;
1488 return *this;
1489 }
1490
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001491 MotionEventBuilder& downTime(nsecs_t downTime) {
1492 mDownTime = downTime;
1493 return *this;
1494 }
1495
Garfield Tandf26e862020-07-01 20:18:19 -07001496 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1497 mEventTime = eventTime;
1498 return *this;
1499 }
1500
1501 MotionEventBuilder& displayId(int32_t displayId) {
1502 mDisplayId = displayId;
1503 return *this;
1504 }
1505
1506 MotionEventBuilder& actionButton(int32_t actionButton) {
1507 mActionButton = actionButton;
1508 return *this;
1509 }
1510
arthurhung6d4bed92021-03-17 11:59:33 +08001511 MotionEventBuilder& buttonState(int32_t buttonState) {
1512 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001513 return *this;
1514 }
1515
1516 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1517 mRawXCursorPosition = rawXCursorPosition;
1518 return *this;
1519 }
1520
1521 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1522 mRawYCursorPosition = rawYCursorPosition;
1523 return *this;
1524 }
1525
1526 MotionEventBuilder& pointer(PointerBuilder pointer) {
1527 mPointers.push_back(pointer);
1528 return *this;
1529 }
1530
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001531 MotionEventBuilder& addFlag(uint32_t flags) {
1532 mFlags |= flags;
1533 return *this;
1534 }
1535
Garfield Tandf26e862020-07-01 20:18:19 -07001536 MotionEvent build() {
1537 std::vector<PointerProperties> pointerProperties;
1538 std::vector<PointerCoords> pointerCoords;
1539 for (const PointerBuilder& pointer : mPointers) {
1540 pointerProperties.push_back(pointer.buildProperties());
1541 pointerCoords.push_back(pointer.buildCoords());
1542 }
1543
1544 // Set mouse cursor position for the most common cases to avoid boilerplate.
1545 if (mSource == AINPUT_SOURCE_MOUSE &&
1546 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1547 mPointers.size() == 1) {
1548 mRawXCursorPosition = pointerCoords[0].getX();
1549 mRawYCursorPosition = pointerCoords[0].getY();
1550 }
1551
1552 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001553 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001554 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001555 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001556 mButtonState, MotionClassification::NONE, identityTransform,
1557 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001558 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001559 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001560
1561 return event;
1562 }
1563
1564private:
1565 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001566 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001567 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001568 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001569 nsecs_t mEventTime;
1570 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1571 int32_t mActionButton{0};
1572 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001573 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001574 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1575 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1576
1577 std::vector<PointerBuilder> mPointers;
1578};
1579
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001580class MotionArgsBuilder {
1581public:
1582 MotionArgsBuilder(int32_t action, int32_t source) {
1583 mAction = action;
1584 mSource = source;
1585 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1586 mDownTime = mEventTime;
1587 }
1588
1589 MotionArgsBuilder& deviceId(int32_t deviceId) {
1590 mDeviceId = deviceId;
1591 return *this;
1592 }
1593
1594 MotionArgsBuilder& downTime(nsecs_t downTime) {
1595 mDownTime = downTime;
1596 return *this;
1597 }
1598
1599 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1600 mEventTime = eventTime;
1601 return *this;
1602 }
1603
1604 MotionArgsBuilder& displayId(int32_t displayId) {
1605 mDisplayId = displayId;
1606 return *this;
1607 }
1608
1609 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1610 mPolicyFlags = policyFlags;
1611 return *this;
1612 }
1613
1614 MotionArgsBuilder& actionButton(int32_t actionButton) {
1615 mActionButton = actionButton;
1616 return *this;
1617 }
1618
1619 MotionArgsBuilder& buttonState(int32_t buttonState) {
1620 mButtonState = buttonState;
1621 return *this;
1622 }
1623
1624 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1625 mRawXCursorPosition = rawXCursorPosition;
1626 return *this;
1627 }
1628
1629 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1630 mRawYCursorPosition = rawYCursorPosition;
1631 return *this;
1632 }
1633
1634 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1635 mPointers.push_back(pointer);
1636 return *this;
1637 }
1638
1639 MotionArgsBuilder& addFlag(uint32_t flags) {
1640 mFlags |= flags;
1641 return *this;
1642 }
1643
1644 NotifyMotionArgs build() {
1645 std::vector<PointerProperties> pointerProperties;
1646 std::vector<PointerCoords> pointerCoords;
1647 for (const PointerBuilder& pointer : mPointers) {
1648 pointerProperties.push_back(pointer.buildProperties());
1649 pointerCoords.push_back(pointer.buildCoords());
1650 }
1651
1652 // Set mouse cursor position for the most common cases to avoid boilerplate.
1653 if (mSource == AINPUT_SOURCE_MOUSE &&
1654 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1655 mPointers.size() == 1) {
1656 mRawXCursorPosition = pointerCoords[0].getX();
1657 mRawYCursorPosition = pointerCoords[0].getY();
1658 }
1659
1660 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1661 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1662 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1663 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1664 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1665 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1666
1667 return args;
1668 }
1669
1670private:
1671 int32_t mAction;
1672 int32_t mDeviceId = DEVICE_ID;
1673 int32_t mSource;
1674 nsecs_t mDownTime;
1675 nsecs_t mEventTime;
1676 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1677 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1678 int32_t mActionButton{0};
1679 int32_t mButtonState{0};
1680 int32_t mFlags{0};
1681 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1682 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1683
1684 std::vector<PointerBuilder> mPointers;
1685};
1686
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001687static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001688 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001689 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001690 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1691 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1692 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1693 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001694}
1695
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001696static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001697 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001698 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001699 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001700 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1701 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001702 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001703 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1704 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001705 MotionEvent event = MotionEventBuilder(action, source)
1706 .displayId(displayId)
1707 .eventTime(eventTime)
1708 .rawXCursorPosition(cursorPosition.x)
1709 .rawYCursorPosition(cursorPosition.y)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001710 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001711 .x(position.x)
1712 .y(position.y))
1713 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001714
1715 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001716 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1717 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001718}
1719
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001720static InputEventInjectionResult injectMotionDown(
1721 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1722 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001723 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001724}
1725
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001726static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001727 int32_t source, int32_t displayId,
1728 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001729 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001730}
1731
Jackal Guof9696682018-10-05 12:23:23 +08001732static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1733 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1734 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001735 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001736 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1737 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001738
1739 return args;
1740}
1741
Prabir Pradhan678438e2023-04-13 19:32:51 +00001742[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1743 int32_t displayId,
1744 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001745 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001746 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1747 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1748 }
1749
chaviwd1c23182019-12-20 18:44:56 -08001750 PointerProperties pointerProperties[pointerCount];
1751 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001752
chaviwd1c23182019-12-20 18:44:56 -08001753 for (size_t i = 0; i < pointerCount; i++) {
1754 pointerProperties[i].clear();
1755 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001756 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001757
chaviwd1c23182019-12-20 18:44:56 -08001758 pointerCoords[i].clear();
1759 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1760 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1761 }
Jackal Guof9696682018-10-05 12:23:23 +08001762
1763 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1764 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001765 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001766 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1767 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001768 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1769 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001770 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1771 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001772
1773 return args;
1774}
1775
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001776static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1777 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1778}
1779
chaviwd1c23182019-12-20 18:44:56 -08001780static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1781 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1782}
1783
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001784static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1785 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001786 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001787}
1788
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001789/**
1790 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1791 * broken channel.
1792 */
1793TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1795 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001796 sp<FakeWindowHandle>::make(application, mDispatcher,
1797 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001798
1799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1800
1801 // Window closes its channel, but the window remains.
1802 window->destroyReceiver();
1803 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1804}
1805
Arthur Hungb92218b2018-08-14 12:00:21 +08001806TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001808 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1809 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001810
Arthur Hung72d8dc32020-03-28 00:48:39 +00001811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1813 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001815
1816 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001817 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001818}
1819
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001820TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001822 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1823 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001824
1825 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1826 // Inject a MotionEvent to an unknown display.
1827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1828 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1829 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1830
1831 // Window should receive motion event.
1832 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1833}
1834
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001835/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001836 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001837 * This test serves as a sanity check for the next test, where setInputWindows is
1838 * called twice.
1839 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001840TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1843 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001844 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001845
1846 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001848 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1849 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001851
1852 // Window should receive motion event.
1853 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1854}
1855
1856/**
1857 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001858 */
1859TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001861 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1862 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001863 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001864
1865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1866 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1869 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001871
1872 // Window should receive motion event.
1873 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1874}
1875
Arthur Hungb92218b2018-08-14 12:00:21 +08001876// The foreground window should receive the first touch down event.
1877TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001879 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001880 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001881 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001883
Arthur Hung72d8dc32020-03-28 00:48:39 +00001884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1886 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001888
1889 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001890 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001891 windowSecond->assertNoEvents();
1892}
1893
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001894/**
1895 * Two windows: A top window, and a wallpaper behind the window.
1896 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1897 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001898 * 1. foregroundWindow <-- dup touch to wallpaper
1899 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 */
1901TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1903 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001904 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001905 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001907 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001908 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909
1910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1912 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1913 {100, 200}))
1914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915
1916 // Both foreground window and its wallpaper should receive the touch down
1917 foregroundWindow->consumeMotionDown();
1918 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1919
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1921 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1922 ADISPLAY_ID_DEFAULT, {110, 200}))
1923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1924
1925 foregroundWindow->consumeMotionMove();
1926 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1927
1928 // Now the foreground window goes away, but the wallpaper stays
1929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1930 foregroundWindow->consumeMotionCancel();
1931 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1932 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1933}
1934
1935/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001936 * Two fingers down on the window, and lift off the first finger.
1937 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1938 * contains a single pointer.
1939 */
1940TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1941 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1942 sp<FakeWindowHandle> window =
1943 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1944
1945 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001946 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1948 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1949 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001950 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001951 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1952 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1953 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1954 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001955 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001956 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1957 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1958 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1959 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001960 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1961 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1962 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1963
1964 // Remove the window. The gesture should be canceled
1965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1966 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1967 window->consumeMotionEvent(
1968 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1969}
1970
1971/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001972 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1973 * with the following differences:
1974 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1975 * clean up the connection.
1976 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1977 * Ensure that there's no crash in the dispatcher.
1978 */
1979TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1981 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001982 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001983 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001984 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001985 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001986 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001987
1988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1990 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1991 {100, 200}))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 // Both foreground window and its wallpaper should receive the touch down
1995 foregroundWindow->consumeMotionDown();
1996 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1997
1998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1999 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2000 ADISPLAY_ID_DEFAULT, {110, 200}))
2001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2002
2003 foregroundWindow->consumeMotionMove();
2004 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2005
2006 // Wallpaper closes its channel, but the window remains.
2007 wallpaperWindow->destroyReceiver();
2008 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2009
2010 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2011 // is no longer valid.
2012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2013 foregroundWindow->consumeMotionCancel();
2014}
2015
Arthur Hungc539dbb2022-12-08 07:45:36 +00002016class ShouldSplitTouchFixture : public InputDispatcherTest,
2017 public ::testing::WithParamInterface<bool> {};
2018INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2019 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002020/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002021 * A single window that receives touch (on top), and a wallpaper window underneath it.
2022 * The top window gets a multitouch gesture.
2023 * Ensure that wallpaper gets the same gesture.
2024 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002027 sp<FakeWindowHandle> foregroundWindow =
2028 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2029 foregroundWindow->setDupTouchToWallpaper(true);
2030 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002031
2032 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002033 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002034 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035
Arthur Hungc539dbb2022-12-08 07:45:36 +00002036 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037
2038 // Touch down on top window
2039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2040 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2041 {100, 100}))
2042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2043
2044 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2047
2048 // Second finger down on the top window
2049 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002050 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002051 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002052 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2053 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002054 .build();
2055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2056 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2057 InputEventInjectionSync::WAIT_FOR_RESULT))
2058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2059
Harry Cutts33476232023-01-30 19:57:29 +00002060 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2061 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002062 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063
2064 const MotionEvent secondFingerUpEvent =
2065 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2066 .displayId(ADISPLAY_ID_DEFAULT)
2067 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002068 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2069 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002070 .build();
2071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2072 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2073 InputEventInjectionSync::WAIT_FOR_RESULT))
2074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2075 foregroundWindow->consumeMotionPointerUp(0);
2076 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2077
2078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002079 injectMotionEvent(mDispatcher,
2080 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2081 AINPUT_SOURCE_TOUCHSCREEN)
2082 .displayId(ADISPLAY_ID_DEFAULT)
2083 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2084 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002085 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002086 .x(100)
2087 .y(100))
2088 .build(),
2089 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2091 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2092 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002093}
2094
2095/**
2096 * Two windows: a window on the left and window on the right.
2097 * A third window, wallpaper, is behind both windows, and spans both top windows.
2098 * The first touch down goes to the left window. A second pointer touches down on the right window.
2099 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2100 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2101 * ACTION_POINTER_DOWN(1).
2102 */
2103TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2105 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002106 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002107 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002108 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002109
2110 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002111 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002112 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002113 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002114
2115 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002116 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002117 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002118 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002119
2120 mDispatcher->setInputWindows(
2121 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2122
2123 // Touch down on left window
2124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2125 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2126 {100, 100}))
2127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2128
2129 // Both foreground window and its wallpaper should receive the touch down
2130 leftWindow->consumeMotionDown();
2131 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2132
2133 // Second finger down on the right window
2134 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002135 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002136 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002137 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2138 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002139 .build();
2140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2141 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2142 InputEventInjectionSync::WAIT_FOR_RESULT))
2143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2144
2145 leftWindow->consumeMotionMove();
2146 // Since the touch is split, right window gets ACTION_DOWN
2147 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002148 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002149 expectedWallpaperFlags);
2150
2151 // Now, leftWindow, which received the first finger, disappears.
2152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2153 leftWindow->consumeMotionCancel();
2154 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2155 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2156
2157 // The pointer that's still down on the right window moves, and goes to the right window only.
2158 // As far as the dispatcher's concerned though, both pointers are still present.
2159 const MotionEvent secondFingerMoveEvent =
2160 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2161 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002162 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2163 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002164 .build();
2165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2166 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2167 InputEventInjectionSync::WAIT_FOR_RESULT));
2168 rightWindow->consumeMotionMove();
2169
2170 leftWindow->assertNoEvents();
2171 rightWindow->assertNoEvents();
2172 wallpaperWindow->assertNoEvents();
2173}
2174
Arthur Hungc539dbb2022-12-08 07:45:36 +00002175/**
2176 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2177 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2178 * The right window should receive ACTION_DOWN.
2179 */
2180TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002182 sp<FakeWindowHandle> leftWindow =
2183 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2184 leftWindow->setFrame(Rect(0, 0, 200, 200));
2185 leftWindow->setDupTouchToWallpaper(true);
2186 leftWindow->setSlippery(true);
2187
2188 sp<FakeWindowHandle> rightWindow =
2189 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2190 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002191
2192 sp<FakeWindowHandle> wallpaperWindow =
2193 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2194 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002195
Arthur Hungc539dbb2022-12-08 07:45:36 +00002196 mDispatcher->setInputWindows(
2197 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002198
Arthur Hungc539dbb2022-12-08 07:45:36 +00002199 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2201 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002202 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002204
2205 // Both foreground window and its wallpaper should receive the touch down
2206 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002207 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2208
Arthur Hungc539dbb2022-12-08 07:45:36 +00002209 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002211 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2212 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2214
Arthur Hungc539dbb2022-12-08 07:45:36 +00002215 leftWindow->consumeMotionCancel();
2216 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2217 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002218}
2219
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002220/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002221 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2222 * interactive, it might stop sending this flag.
2223 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2224 * to have a consistent input stream.
2225 *
2226 * Test procedure:
2227 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2228 * DOWN (new gesture).
2229 *
2230 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2231 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2232 *
2233 * We technically just need a single window here, but we are using two windows (spy on top and a
2234 * regular window below) to emulate the actual situation where it happens on the device.
2235 */
2236TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2238 sp<FakeWindowHandle> spyWindow =
2239 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2240 spyWindow->setFrame(Rect(0, 0, 200, 200));
2241 spyWindow->setTrustedOverlay(true);
2242 spyWindow->setSpy(true);
2243
2244 sp<FakeWindowHandle> window =
2245 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2246 window->setFrame(Rect(0, 0, 200, 200));
2247
2248 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2249 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002250
2251 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002252 mDispatcher->notifyMotion(
2253 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2254 .deviceId(touchDeviceId)
2255 .policyFlags(DEFAULT_POLICY_FLAGS)
2256 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2257 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002258
Prabir Pradhan678438e2023-04-13 19:32:51 +00002259 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2260 .deviceId(touchDeviceId)
2261 .policyFlags(DEFAULT_POLICY_FLAGS)
2262 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2263 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2264 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002265 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2266 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2267 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2268 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2269
2270 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002271 mDispatcher->notifyMotion(
2272 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .policyFlags(0)
2275 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2276 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2277 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002278 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2279 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2280
2281 // We don't need to reset the device to reproduce the issue, but the reset event typically
2282 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002283 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002284
2285 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002286 mDispatcher->notifyMotion(
2287 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2288 .deviceId(touchDeviceId)
2289 .policyFlags(DEFAULT_POLICY_FLAGS)
2290 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2291 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002292 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2293 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2294
2295 // No more events
2296 spyWindow->assertNoEvents();
2297 window->assertNoEvents();
2298}
2299
2300/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002301 * Two windows: a window on the left and a window on the right.
2302 * Mouse is hovered from the right window into the left window.
2303 * Next, we tap on the left window, where the cursor was last seen.
2304 * The second tap is done onto the right window.
2305 * The mouse and tap are from two different devices.
2306 * We technically don't need to set the downtime / eventtime for these events, but setting these
2307 * explicitly helps during debugging.
2308 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2309 * In the buggy implementation, a tap on the right window would cause a crash.
2310 */
2311TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2313 sp<FakeWindowHandle> leftWindow =
2314 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2315 leftWindow->setFrame(Rect(0, 0, 200, 200));
2316
2317 sp<FakeWindowHandle> rightWindow =
2318 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2319 rightWindow->setFrame(Rect(200, 0, 400, 200));
2320
2321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2322 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2323 // stale.
2324 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2325 const int32_t mouseDeviceId = 6;
2326 const int32_t touchDeviceId = 4;
2327 // Move the cursor from right
2328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2329 injectMotionEvent(mDispatcher,
2330 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2331 AINPUT_SOURCE_MOUSE)
2332 .deviceId(mouseDeviceId)
2333 .downTime(baseTime + 10)
2334 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002335 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002336 .x(300)
2337 .y(100))
2338 .build()));
2339 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2340
2341 // .. to the left window
2342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2343 injectMotionEvent(mDispatcher,
2344 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2345 AINPUT_SOURCE_MOUSE)
2346 .deviceId(mouseDeviceId)
2347 .downTime(baseTime + 10)
2348 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002349 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002350 .x(110)
2351 .y(100))
2352 .build()));
2353 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2354 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2355 // Now tap the left window
2356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2357 injectMotionEvent(mDispatcher,
2358 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2359 AINPUT_SOURCE_TOUCHSCREEN)
2360 .deviceId(touchDeviceId)
2361 .downTime(baseTime + 40)
2362 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002363 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002364 .x(100)
2365 .y(100))
2366 .build()));
2367 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2368 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2369
2370 // release tap
2371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2372 injectMotionEvent(mDispatcher,
2373 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2374 AINPUT_SOURCE_TOUCHSCREEN)
2375 .deviceId(touchDeviceId)
2376 .downTime(baseTime + 40)
2377 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002378 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002379 .x(100)
2380 .y(100))
2381 .build()));
2382 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2383
2384 // Tap the window on the right
2385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2386 injectMotionEvent(mDispatcher,
2387 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2388 AINPUT_SOURCE_TOUCHSCREEN)
2389 .deviceId(touchDeviceId)
2390 .downTime(baseTime + 60)
2391 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002392 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002393 .x(300)
2394 .y(100))
2395 .build()));
2396 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2397
2398 // release tap
2399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2400 injectMotionEvent(mDispatcher,
2401 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2402 AINPUT_SOURCE_TOUCHSCREEN)
2403 .deviceId(touchDeviceId)
2404 .downTime(baseTime + 60)
2405 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002406 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002407 .x(300)
2408 .y(100))
2409 .build()));
2410 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2411
2412 // No more events
2413 leftWindow->assertNoEvents();
2414 rightWindow->assertNoEvents();
2415}
2416
2417/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002418 * Two windows: a window on the left and a window on the right.
2419 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2420 * down. Then, on the left window, also place second touch pointer down.
2421 * This test tries to reproduce a crash.
2422 * In the buggy implementation, second pointer down on the left window would cause a crash.
2423 */
2424TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2426 sp<FakeWindowHandle> leftWindow =
2427 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2428 leftWindow->setFrame(Rect(0, 0, 200, 200));
2429
2430 sp<FakeWindowHandle> rightWindow =
2431 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2432 rightWindow->setFrame(Rect(200, 0, 400, 200));
2433
2434 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2435
2436 const int32_t touchDeviceId = 4;
2437 const int32_t mouseDeviceId = 6;
2438 NotifyMotionArgs args;
2439
2440 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2442 .deviceId(mouseDeviceId)
2443 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2444 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002445 leftWindow->consumeMotionEvent(
2446 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2447
2448 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2450 .deviceId(mouseDeviceId)
2451 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2452 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2453 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002454
2455 leftWindow->consumeMotionEvent(
2456 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2457 leftWindow->consumeMotionEvent(
2458 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2459
Prabir Pradhan678438e2023-04-13 19:32:51 +00002460 mDispatcher->notifyMotion(
2461 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2462 .deviceId(mouseDeviceId)
2463 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2464 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2465 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2466 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002467 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2468
2469 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2471 .deviceId(touchDeviceId)
2472 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2473 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002474 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2475
2476 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2477
2478 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002479 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2480 .deviceId(touchDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2482 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2483 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002484 leftWindow->consumeMotionEvent(
2485 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2486 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2487 // current implementation.
2488 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2489 rightWindow->consumeMotionEvent(
2490 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2491
2492 leftWindow->assertNoEvents();
2493 rightWindow->assertNoEvents();
2494}
2495
2496/**
2497 * On a single window, use two different devices: mouse and touch.
2498 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2499 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2500 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2501 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2502 * represent a new gesture.
2503 */
2504TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2505 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2506 sp<FakeWindowHandle> window =
2507 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2508 window->setFrame(Rect(0, 0, 400, 400));
2509
2510 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2511
2512 const int32_t touchDeviceId = 4;
2513 const int32_t mouseDeviceId = 6;
2514 NotifyMotionArgs args;
2515
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002516 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2518 .deviceId(touchDeviceId)
2519 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2520 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002521 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002522 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2523 .deviceId(touchDeviceId)
2524 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2525 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002527 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002528 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2529 .deviceId(touchDeviceId)
2530 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2531 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2532 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002533 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2534 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2535 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2536
2537 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2539 .deviceId(mouseDeviceId)
2540 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2541 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2542 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002543
2544 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002545 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002546 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2547
Prabir Pradhan678438e2023-04-13 19:32:51 +00002548 mDispatcher->notifyMotion(
2549 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2550 .deviceId(mouseDeviceId)
2551 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2552 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2553 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2554 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002555 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2556
2557 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002558 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2559 .deviceId(touchDeviceId)
2560 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2561 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2562 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002563 // The pointer_down event should be ignored
2564 window->assertNoEvents();
2565}
2566
2567/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002568 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2569 * the injected event.
2570 */
2571TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2573 sp<FakeWindowHandle> window =
2574 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2575 window->setFrame(Rect(0, 0, 400, 400));
2576
2577 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2578
2579 const int32_t touchDeviceId = 4;
2580 NotifyMotionArgs args;
2581 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2582 // completion.
2583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2584 injectMotionEvent(mDispatcher,
2585 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2586 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002587 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002588 .x(50)
2589 .y(50))
2590 .build()));
2591 window->consumeMotionEvent(
2592 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2593
2594 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2595 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2597 .deviceId(touchDeviceId)
2598 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2599 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002600
2601 window->consumeMotionEvent(
2602 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2603 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2604}
2605
2606/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002607 * This test is similar to the test above, but the sequence of injected events is different.
2608 *
2609 * Two windows: a window on the left and a window on the right.
2610 * Mouse is hovered over the left window.
2611 * Next, we tap on the left window, where the cursor was last seen.
2612 *
2613 * After that, we inject one finger down onto the right window, and then a second finger down onto
2614 * the left window.
2615 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2616 * window (first), and then another on the left window (second).
2617 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2618 * In the buggy implementation, second finger down on the left window would cause a crash.
2619 */
2620TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2621 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2622 sp<FakeWindowHandle> leftWindow =
2623 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2624 leftWindow->setFrame(Rect(0, 0, 200, 200));
2625
2626 sp<FakeWindowHandle> rightWindow =
2627 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2628 rightWindow->setFrame(Rect(200, 0, 400, 200));
2629
2630 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2631
2632 const int32_t mouseDeviceId = 6;
2633 const int32_t touchDeviceId = 4;
2634 // Hover over the left window. Keep the cursor there.
2635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2636 injectMotionEvent(mDispatcher,
2637 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2638 AINPUT_SOURCE_MOUSE)
2639 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002640 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002641 .x(50)
2642 .y(50))
2643 .build()));
2644 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2645
2646 // Tap on left window
2647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2648 injectMotionEvent(mDispatcher,
2649 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2650 AINPUT_SOURCE_TOUCHSCREEN)
2651 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002652 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002653 .x(100)
2654 .y(100))
2655 .build()));
2656
2657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2658 injectMotionEvent(mDispatcher,
2659 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2660 AINPUT_SOURCE_TOUCHSCREEN)
2661 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002662 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002663 .x(100)
2664 .y(100))
2665 .build()));
2666 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2667 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2668 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2669
2670 // First finger down on right window
2671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2672 injectMotionEvent(mDispatcher,
2673 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2674 AINPUT_SOURCE_TOUCHSCREEN)
2675 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002676 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002677 .x(300)
2678 .y(100))
2679 .build()));
2680 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2681
2682 // Second finger down on the left window
2683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2684 injectMotionEvent(mDispatcher,
2685 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2686 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002687 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002688 .x(300)
2689 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002690 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002691 .x(100)
2692 .y(100))
2693 .build()));
2694 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2695 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2696
2697 // No more events
2698 leftWindow->assertNoEvents();
2699 rightWindow->assertNoEvents();
2700}
2701
2702/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002703 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2704 * While the touch is down, new hover events from the stylus device should be ignored. After the
2705 * touch is gone, stylus hovering should start working again.
2706 */
2707TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2709 sp<FakeWindowHandle> window =
2710 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2711 window->setFrame(Rect(0, 0, 200, 200));
2712
2713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2714
2715 const int32_t stylusDeviceId = 5;
2716 const int32_t touchDeviceId = 4;
2717 // Start hovering with stylus
2718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2719 injectMotionEvent(mDispatcher,
2720 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2721 AINPUT_SOURCE_STYLUS)
2722 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002723 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002724 .x(50)
2725 .y(50))
2726 .build()));
2727 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2728
2729 // Finger down on the window
2730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2731 injectMotionEvent(mDispatcher,
2732 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2733 AINPUT_SOURCE_TOUCHSCREEN)
2734 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002735 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002736 .x(100)
2737 .y(100))
2738 .build()));
2739 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2740 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2741
2742 // Try to continue hovering with stylus. Since we are already down, injection should fail
2743 ASSERT_EQ(InputEventInjectionResult::FAILED,
2744 injectMotionEvent(mDispatcher,
2745 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2746 AINPUT_SOURCE_STYLUS)
2747 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002748 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002749 .x(50)
2750 .y(50))
2751 .build()));
2752 // No event should be sent. This event should be ignored because a pointer from another device
2753 // is already down.
2754
2755 // Lift up the finger
2756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2757 injectMotionEvent(mDispatcher,
2758 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2759 AINPUT_SOURCE_TOUCHSCREEN)
2760 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002761 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002762 .x(100)
2763 .y(100))
2764 .build()));
2765 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2766
2767 // Now that the touch is gone, stylus hovering should start working again
2768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2769 injectMotionEvent(mDispatcher,
2770 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2771 AINPUT_SOURCE_STYLUS)
2772 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002773 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002774 .x(50)
2775 .y(50))
2776 .build()));
2777 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2778 // No more events
2779 window->assertNoEvents();
2780}
2781
2782/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002783 * A spy window above a window with no input channel.
2784 * Start hovering with a stylus device, and then tap with it.
2785 * Ensure spy window receives the entire sequence.
2786 */
2787TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2789 sp<FakeWindowHandle> spyWindow =
2790 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2791 spyWindow->setFrame(Rect(0, 0, 200, 200));
2792 spyWindow->setTrustedOverlay(true);
2793 spyWindow->setSpy(true);
2794 sp<FakeWindowHandle> window =
2795 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2796 window->setNoInputChannel(true);
2797 window->setFrame(Rect(0, 0, 200, 200));
2798
2799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2800
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002801 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2803 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2804 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002805 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2806 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2808 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2809 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002810 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2811
2812 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2814 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2815 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002816 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2817
2818 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2820 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2821 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002822 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2823
2824 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2827 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002828 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2829 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2831 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2832 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002833 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2834
2835 // No more events
2836 spyWindow->assertNoEvents();
2837 window->assertNoEvents();
2838}
2839
2840/**
2841 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2842 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2843 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2844 * While the mouse is down, new move events from the touch device should be ignored.
2845 */
2846TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2848 sp<FakeWindowHandle> spyWindow =
2849 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2850 spyWindow->setFrame(Rect(0, 0, 200, 200));
2851 spyWindow->setTrustedOverlay(true);
2852 spyWindow->setSpy(true);
2853 sp<FakeWindowHandle> window =
2854 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2855 window->setFrame(Rect(0, 0, 200, 200));
2856
2857 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2858
2859 const int32_t mouseDeviceId = 7;
2860 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002861
2862 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2864 .deviceId(mouseDeviceId)
2865 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2866 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002867 spyWindow->consumeMotionEvent(
2868 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2869 window->consumeMotionEvent(
2870 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2871
2872 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2874 .deviceId(touchDeviceId)
2875 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2876 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002877 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2880 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2881
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2883 .deviceId(touchDeviceId)
2884 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2885 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002886 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2887 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2888
2889 // Pilfer the stream
2890 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2891 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2892
Prabir Pradhan678438e2023-04-13 19:32:51 +00002893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2894 .deviceId(touchDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002897 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2898
2899 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2901 .deviceId(mouseDeviceId)
2902 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2903 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2904 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002905
2906 spyWindow->consumeMotionEvent(
2907 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2908 spyWindow->consumeMotionEvent(
2909 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2910 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2911
Prabir Pradhan678438e2023-04-13 19:32:51 +00002912 mDispatcher->notifyMotion(
2913 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2914 .deviceId(mouseDeviceId)
2915 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2916 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2917 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2918 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002919 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2920 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2921
2922 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2924 .deviceId(mouseDeviceId)
2925 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2926 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2927 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002928 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2929 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2930
2931 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2933 .deviceId(touchDeviceId)
2934 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936
2937 // No more events
2938 spyWindow->assertNoEvents();
2939 window->assertNoEvents();
2940}
2941
2942/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002943 * On the display, have a single window, and also an area where there's no window.
2944 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2945 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2946 */
2947TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2949 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002950 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002951
2952 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002953
2954 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002955 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002956
2957 mDispatcher->waitForIdle();
2958 window->assertNoEvents();
2959
2960 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002962 mDispatcher->waitForIdle();
2963 window->consumeMotionDown();
2964}
2965
2966/**
2967 * Same test as above, but instead of touching the empty space, the first touch goes to
2968 * non-touchable window.
2969 */
2970TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2972 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002973 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002974 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2975 window1->setTouchable(false);
2976 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002977 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002978 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2979
2980 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2981
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002982 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002983 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002984
2985 mDispatcher->waitForIdle();
2986 window1->assertNoEvents();
2987 window2->assertNoEvents();
2988
2989 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002990 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002991 mDispatcher->waitForIdle();
2992 window2->consumeMotionDown();
2993}
2994
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002995/**
2996 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2997 * to the event time of the first ACTION_DOWN sent to the particular window.
2998 */
2999TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3000 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3001 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003002 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003003 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3004 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003005 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003006 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3007
3008 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3009
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003010 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003011 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003012
3013 mDispatcher->waitForIdle();
3014 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003015 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003016 window2->assertNoEvents();
3017 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3018 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3019 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3020
3021 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003022 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003023 mDispatcher->waitForIdle();
3024 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003025 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003026 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3027 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3028 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3029 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3030
3031 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003032 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003033 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003034 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003035
3036 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003037 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003038 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003039 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003040
3041 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3042 window1->consumeMotionMove();
3043 window1->assertNoEvents();
3044
3045 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003046 mDispatcher->notifyMotion(
3047 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003048 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003049 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003050
Prabir Pradhan678438e2023-04-13 19:32:51 +00003051 mDispatcher->notifyMotion(
3052 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003053 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003054 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003055}
3056
Garfield Tandf26e862020-07-01 20:18:19 -07003057TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003059 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003060 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003061 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003062 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003063 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003064 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003065
3066 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3067
3068 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3069
3070 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003072 injectMotionEvent(mDispatcher,
3073 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3074 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003075 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003076 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003077 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003078
3079 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003081 injectMotionEvent(mDispatcher,
3082 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3083 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003084 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003085 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003086 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3087 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003088
3089 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003091 injectMotionEvent(mDispatcher,
3092 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3093 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003094 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003095 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3097 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003098
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003100 injectMotionEvent(mDispatcher,
3101 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3102 AINPUT_SOURCE_MOUSE)
3103 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3104 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003105 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003106 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003107 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003108
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003110 injectMotionEvent(mDispatcher,
3111 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3112 AINPUT_SOURCE_MOUSE)
3113 .buttonState(0)
3114 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003115 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003116 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003117 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003118
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003120 injectMotionEvent(mDispatcher,
3121 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3122 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003123 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003124 .build()));
3125 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3126
3127 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003129 injectMotionEvent(mDispatcher,
3130 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3131 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003132 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003133 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003134 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003135
3136 // No more events
3137 windowLeft->assertNoEvents();
3138 windowRight->assertNoEvents();
3139}
3140
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003141/**
3142 * Put two fingers down (and don't release them) and click the mouse button.
3143 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3144 * currently active gesture should be canceled, and the new one should proceed.
3145 */
3146TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3148 sp<FakeWindowHandle> window =
3149 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3150 window->setFrame(Rect(0, 0, 600, 800));
3151
3152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3153
3154 const int32_t touchDeviceId = 4;
3155 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003156
3157 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3159 .deviceId(touchDeviceId)
3160 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3161 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003162
Prabir Pradhan678438e2023-04-13 19:32:51 +00003163 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3164 .deviceId(touchDeviceId)
3165 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3166 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3167 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003168 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3169 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3170
3171 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3173 .deviceId(mouseDeviceId)
3174 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3175 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3176 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003177 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3178 WithPointerCount(2u)));
3179 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3180
Prabir Pradhan678438e2023-04-13 19:32:51 +00003181 mDispatcher->notifyMotion(
3182 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3183 .deviceId(mouseDeviceId)
3184 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3185 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3186 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3187 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003188 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3189
3190 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3191 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003192 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3193 .deviceId(touchDeviceId)
3194 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3195 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3196 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197 window->assertNoEvents();
3198}
3199
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003200TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3201 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3202
3203 sp<FakeWindowHandle> spyWindow =
3204 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3205 spyWindow->setFrame(Rect(0, 0, 600, 800));
3206 spyWindow->setTrustedOverlay(true);
3207 spyWindow->setSpy(true);
3208 sp<FakeWindowHandle> window =
3209 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3210 window->setFrame(Rect(0, 0, 600, 800));
3211
3212 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3214
3215 // Send mouse cursor to the window
3216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3217 injectMotionEvent(mDispatcher,
3218 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3219 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003220 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003221 .x(100)
3222 .y(100))
3223 .build()));
3224
3225 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3226 WithSource(AINPUT_SOURCE_MOUSE)));
3227 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3228 WithSource(AINPUT_SOURCE_MOUSE)));
3229
3230 window->assertNoEvents();
3231 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003232}
3233
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003234TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3236
3237 sp<FakeWindowHandle> spyWindow =
3238 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3239 spyWindow->setFrame(Rect(0, 0, 600, 800));
3240 spyWindow->setTrustedOverlay(true);
3241 spyWindow->setSpy(true);
3242 sp<FakeWindowHandle> window =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3244 window->setFrame(Rect(0, 0, 600, 800));
3245
3246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3247 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3248
3249 // Send mouse cursor to the window
3250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3251 injectMotionEvent(mDispatcher,
3252 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3253 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003254 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003255 .x(100)
3256 .y(100))
3257 .build()));
3258
3259 // Move mouse cursor
3260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3261 injectMotionEvent(mDispatcher,
3262 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3263 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003264 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003265 .x(110)
3266 .y(110))
3267 .build()));
3268
3269 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3270 WithSource(AINPUT_SOURCE_MOUSE)));
3271 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3272 WithSource(AINPUT_SOURCE_MOUSE)));
3273 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3274 WithSource(AINPUT_SOURCE_MOUSE)));
3275 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3276 WithSource(AINPUT_SOURCE_MOUSE)));
3277 // Touch down on the window
3278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3279 injectMotionEvent(mDispatcher,
3280 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3281 AINPUT_SOURCE_TOUCHSCREEN)
3282 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003283 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003284 .x(200)
3285 .y(200))
3286 .build()));
3287 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3288 WithSource(AINPUT_SOURCE_MOUSE)));
3289 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3290 WithSource(AINPUT_SOURCE_MOUSE)));
3291 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3292 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3293 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3294 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3295
3296 // pilfer the motion, retaining the gesture on the spy window.
3297 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3298 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3299 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3300
3301 // Touch UP on the window
3302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3303 injectMotionEvent(mDispatcher,
3304 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3305 AINPUT_SOURCE_TOUCHSCREEN)
3306 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003307 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003308 .x(200)
3309 .y(200))
3310 .build()));
3311 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3312 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3313
3314 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3315 // to send a new gesture. It should again go to both windows (spy and the window below), just
3316 // like the first gesture did, before pilfering. The window configuration has not changed.
3317
3318 // One more tap - DOWN
3319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3320 injectMotionEvent(mDispatcher,
3321 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3322 AINPUT_SOURCE_TOUCHSCREEN)
3323 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003324 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003325 .x(250)
3326 .y(250))
3327 .build()));
3328 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3329 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3330 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3331 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3332
3333 // Touch UP on the window
3334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3335 injectMotionEvent(mDispatcher,
3336 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3337 AINPUT_SOURCE_TOUCHSCREEN)
3338 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003339 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003340 .x(250)
3341 .y(250))
3342 .build()));
3343 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3344 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3345 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3346 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3347
3348 window->assertNoEvents();
3349 spyWindow->assertNoEvents();
3350}
3351
Garfield Tandf26e862020-07-01 20:18:19 -07003352// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3353// directly in this test.
3354TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003355 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003356 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003357 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003358 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003359
3360 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3361
3362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3363
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003365 injectMotionEvent(mDispatcher,
3366 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3367 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003368 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003369 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003370 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003371 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003373 injectMotionEvent(mDispatcher,
3374 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3375 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003376 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003377 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003378 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3379 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003380
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003382 injectMotionEvent(mDispatcher,
3383 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3384 AINPUT_SOURCE_MOUSE)
3385 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3386 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003387 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003388 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003389 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003390
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003392 injectMotionEvent(mDispatcher,
3393 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3394 AINPUT_SOURCE_MOUSE)
3395 .buttonState(0)
3396 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003397 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003398 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003399 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003400
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003402 injectMotionEvent(mDispatcher,
3403 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3404 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003405 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003406 .build()));
3407 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3408
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003410 injectMotionEvent(mDispatcher,
3411 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3412 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003414 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003415 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003416}
3417
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003418/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003419 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3420 * is generated.
3421 */
3422TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3424 sp<FakeWindowHandle> window =
3425 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3426 window->setFrame(Rect(0, 0, 1200, 800));
3427
3428 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3429
3430 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3431
3432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3433 injectMotionEvent(mDispatcher,
3434 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3435 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003436 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003437 .x(300)
3438 .y(400))
3439 .build()));
3440 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3441
3442 // Remove the window, but keep the channel.
3443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3444 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3445}
3446
3447/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003448 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3449 */
3450TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3452 sp<FakeWindowHandle> window =
3453 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3454 window->setFrame(Rect(0, 0, 100, 100));
3455
3456 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3457
3458 const int32_t mouseDeviceId = 7;
3459 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003460
3461 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3463 .deviceId(mouseDeviceId)
3464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3465 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003466 window->consumeMotionEvent(
3467 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3468
3469 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3471 .deviceId(touchDeviceId)
3472 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3473 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003474
3475 window->consumeMotionEvent(
3476 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3477 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3478}
3479
3480/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003481 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003482 * The tap causes a HOVER_EXIT event to be generated because the current event
3483 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003484 */
3485TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3487 sp<FakeWindowHandle> window =
3488 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3489 window->setFrame(Rect(0, 0, 100, 100));
3490
3491 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3492
3493 // Inject a hover_move from mouse.
3494 NotifyMotionArgs motionArgs =
3495 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3496 ADISPLAY_ID_DEFAULT, {{50, 50}});
3497 motionArgs.xCursorPosition = 50;
3498 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003499 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003500 ASSERT_NO_FATAL_FAILURE(
3501 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3502 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003503
3504 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3506 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3507 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003508 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003509 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3510 WithSource(AINPUT_SOURCE_MOUSE))));
3511
3512 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003513 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3514 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3515
Prabir Pradhan678438e2023-04-13 19:32:51 +00003516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3517 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003518 ASSERT_NO_FATAL_FAILURE(
3519 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3520 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3521}
3522
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003523TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3525 sp<FakeWindowHandle> windowDefaultDisplay =
3526 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3527 ADISPLAY_ID_DEFAULT);
3528 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3529 sp<FakeWindowHandle> windowSecondDisplay =
3530 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3531 SECOND_DISPLAY_ID);
3532 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3533
3534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3535 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3536
3537 // Set cursor position in window in default display and check that hover enter and move
3538 // events are generated.
3539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3540 injectMotionEvent(mDispatcher,
3541 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3542 AINPUT_SOURCE_MOUSE)
3543 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003544 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003545 .x(300)
3546 .y(600))
3547 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003548 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003549
3550 // Remove all windows in secondary display and check that no event happens on window in
3551 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003552 mDispatcher->setInputWindows(
3553 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003554 windowDefaultDisplay->assertNoEvents();
3555
3556 // Move cursor position in window in default display and check that only hover move
3557 // event is generated and not hover enter event.
3558 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3559 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3561 injectMotionEvent(mDispatcher,
3562 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3563 AINPUT_SOURCE_MOUSE)
3564 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003565 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003566 .x(400)
3567 .y(700))
3568 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003569 windowDefaultDisplay->consumeMotionEvent(
3570 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3571 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003572 windowDefaultDisplay->assertNoEvents();
3573}
3574
Garfield Tan00f511d2019-06-12 16:55:40 -07003575TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003576 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003577
3578 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003579 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003580 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003581 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003582 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003583 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003584
3585 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3586
Arthur Hung72d8dc32020-03-28 00:48:39 +00003587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003588
3589 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3590 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003592 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003593 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003594 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003595 windowRight->assertNoEvents();
3596}
3597
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003598TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003600 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3601 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003602 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003603
Arthur Hung72d8dc32020-03-28 00:48:39 +00003604 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003605 setFocusedWindow(window);
3606
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003607 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003608
Prabir Pradhan678438e2023-04-13 19:32:51 +00003609 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003610
3611 // Window should receive key down event.
3612 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3613
3614 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3615 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003616 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003617 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003618 AKEY_EVENT_FLAG_CANCELED);
3619}
3620
3621TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003623 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3624 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003625
Arthur Hung72d8dc32020-03-28 00:48:39 +00003626 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003627
Prabir Pradhan678438e2023-04-13 19:32:51 +00003628 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3629 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003630
3631 // Window should receive motion down event.
3632 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3633
3634 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3635 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003636 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003637 window->consumeMotionEvent(
3638 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003639}
3640
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003641TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003643 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3644 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003645 window->setFocusable(true);
3646
3647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3648 setFocusedWindow(window);
3649
3650 window->consumeFocusEvent(true);
3651
Prabir Pradhan678438e2023-04-13 19:32:51 +00003652 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003653 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3654 const nsecs_t injectTime = keyArgs.eventTime;
3655 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003656 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003657 // The dispatching time should be always greater than or equal to intercept key timeout.
3658 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3659 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3660 std::chrono::nanoseconds(interceptKeyTimeout).count());
3661}
3662
3663TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3666 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003667 window->setFocusable(true);
3668
3669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3670 setFocusedWindow(window);
3671
3672 window->consumeFocusEvent(true);
3673
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003674 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003675 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3676 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003677
3678 // Window should receive key event immediately when same key up.
3679 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3680 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3681}
3682
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003683/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003684 * Two windows. First is a regular window. Second does not overlap with the first, and has
3685 * WATCH_OUTSIDE_TOUCH.
3686 * Both windows are owned by the same UID.
3687 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3688 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3689 */
3690TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3693 "First Window", ADISPLAY_ID_DEFAULT);
3694 window->setFrame(Rect{0, 0, 100, 100});
3695
3696 sp<FakeWindowHandle> outsideWindow =
3697 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3698 ADISPLAY_ID_DEFAULT);
3699 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3700 outsideWindow->setWatchOutsideTouch(true);
3701 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3702 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3703
3704 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003705 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3706 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3707 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003708 window->consumeMotionDown();
3709 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3710 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3711 outsideWindow->consumeMotionEvent(
3712 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3713}
3714
3715/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003716 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3717 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3718 * ACTION_OUTSIDE event is sent per gesture.
3719 */
3720TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3721 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3724 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003725 window->setWatchOutsideTouch(true);
3726 window->setFrame(Rect{0, 0, 100, 100});
3727 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003728 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3729 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003730 secondWindow->setFrame(Rect{100, 100, 200, 200});
3731 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003732 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3733 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003734 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3736
3737 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003738 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3739 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3740 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003741 window->assertNoEvents();
3742 secondWindow->assertNoEvents();
3743
3744 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3745 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003746 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3747 ADISPLAY_ID_DEFAULT,
3748 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003749 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3750 window->consumeMotionEvent(
3751 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003752 secondWindow->consumeMotionDown();
3753 thirdWindow->assertNoEvents();
3754
3755 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3756 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(
3758 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3759 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003760 window->assertNoEvents();
3761 secondWindow->consumeMotionMove();
3762 thirdWindow->consumeMotionDown();
3763}
3764
Prabir Pradhan814fe082022-07-22 20:22:18 +00003765TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003767 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3768 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003769 window->setFocusable(true);
3770
3771 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3772 setFocusedWindow(window);
3773
3774 window->consumeFocusEvent(true);
3775
Prabir Pradhan678438e2023-04-13 19:32:51 +00003776 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3777 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3778 mDispatcher->notifyKey(keyDown);
3779 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003780
3781 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3782 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3783
3784 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3785 mDispatcher->onWindowInfosChanged({}, {});
3786
3787 window->consumeFocusEvent(false);
3788
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyKey(keyDown);
3790 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003791 window->assertNoEvents();
3792}
3793
Arthur Hung96483742022-11-15 03:30:48 +00003794TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3797 "Fake Window", ADISPLAY_ID_DEFAULT);
3798 // Ensure window is non-split and have some transform.
3799 window->setPreventSplitting(true);
3800 window->setWindowOffset(20, 40);
3801 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3802
3803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3804 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3805 {50, 50}))
3806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3807 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3808
3809 const MotionEvent secondFingerDownEvent =
3810 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3811 .displayId(ADISPLAY_ID_DEFAULT)
3812 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003813 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3814 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003815 .build();
3816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3817 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3818 InputEventInjectionSync::WAIT_FOR_RESULT))
3819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3820
3821 const MotionEvent* event = window->consumeMotion();
3822 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3823 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3824 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3825 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3826 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3827}
3828
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003829/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003830 * Ensure the correct coordinate spaces are used by InputDispatcher.
3831 *
3832 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3833 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3834 * space.
3835 */
3836class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3837public:
3838 void SetUp() override {
3839 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003840 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003841 }
3842
3843 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3844 gui::DisplayInfo info;
3845 info.displayId = displayId;
3846 info.transform = transform;
3847 mDisplayInfos.push_back(std::move(info));
3848 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3849 }
3850
3851 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3852 mWindowInfos.push_back(*windowHandle->getInfo());
3853 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3854 }
3855
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003856 void removeAllWindowsAndDisplays() {
3857 mDisplayInfos.clear();
3858 mWindowInfos.clear();
3859 }
3860
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003861 // Set up a test scenario where the display has a scaled projection and there are two windows
3862 // on the display.
3863 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3864 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3865 // respectively.
3866 ui::Transform displayTransform;
3867 displayTransform.set(2, 0, 0, 4);
3868 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3869
3870 std::shared_ptr<FakeApplicationHandle> application =
3871 std::make_shared<FakeApplicationHandle>();
3872
3873 // Add two windows to the display. Their frames are represented in the display space.
3874 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003875 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3876 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003877 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3878 addWindow(firstWindow);
3879
3880 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003881 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3882 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003883 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3884 addWindow(secondWindow);
3885 return {std::move(firstWindow), std::move(secondWindow)};
3886 }
3887
3888private:
3889 std::vector<gui::DisplayInfo> mDisplayInfos;
3890 std::vector<gui::WindowInfo> mWindowInfos;
3891};
3892
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003893TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003894 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3895 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003896 // selected so that if the hit test was performed with the point and the bounds being in
3897 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003898 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3899 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3900 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003901
3902 firstWindow->consumeMotionDown();
3903 secondWindow->assertNoEvents();
3904}
3905
3906// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3907// the event should be treated as being in the logical display space.
3908TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3909 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3910 // Send down to the first window. The point is represented in the logical display space. The
3911 // point is selected so that if the hit test was done in logical display space, then it would
3912 // end up in the incorrect window.
3913 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3914 PointF{75 * 2, 55 * 4});
3915
3916 firstWindow->consumeMotionDown();
3917 secondWindow->assertNoEvents();
3918}
3919
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003920// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3921// event should be treated as being in the logical display space.
3922TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3923 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3924
3925 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3926 ui::Transform injectedEventTransform;
3927 injectedEventTransform.set(matrix);
3928 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3929 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3930
3931 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3932 .displayId(ADISPLAY_ID_DEFAULT)
3933 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003934 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003935 .x(untransformedPoint.x)
3936 .y(untransformedPoint.y))
3937 .build();
3938 event.transform(matrix);
3939
3940 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
3941 InputEventInjectionSync::WAIT_FOR_RESULT);
3942
3943 firstWindow->consumeMotionDown();
3944 secondWindow->assertNoEvents();
3945}
3946
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003947TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
3948 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3949
3950 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003951 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3952 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3953 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003954
3955 firstWindow->assertNoEvents();
3956 const MotionEvent* event = secondWindow->consumeMotion();
3957 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
3958
3959 // Ensure that the events from the "getRaw" API are in logical display coordinates.
3960 EXPECT_EQ(300, event->getRawX(0));
3961 EXPECT_EQ(880, event->getRawY(0));
3962
3963 // Ensure that the x and y values are in the window's coordinate space.
3964 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
3965 // the logical display space. This will be the origin of the window space.
3966 EXPECT_EQ(100, event->getX(0));
3967 EXPECT_EQ(80, event->getY(0));
3968}
3969
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003970/** Ensure consistent behavior of InputDispatcher in all orientations. */
3971class InputDispatcherDisplayOrientationFixture
3972 : public InputDispatcherDisplayProjectionTest,
3973 public ::testing::WithParamInterface<ui::Rotation> {};
3974
3975// This test verifies the touchable region of a window for all rotations of the display by tapping
3976// in different locations on the display, specifically points close to the four corners of a
3977// window.
3978TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
3979 constexpr static int32_t displayWidth = 400;
3980 constexpr static int32_t displayHeight = 800;
3981
3982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3983
3984 const auto rotation = GetParam();
3985
3986 // Set up the display with the specified rotation.
3987 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
3988 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
3989 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
3990 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
3991 logicalDisplayWidth, logicalDisplayHeight);
3992 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3993
3994 // Create a window with its bounds determined in the logical display.
3995 const Rect frameInLogicalDisplay(100, 100, 200, 300);
3996 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
3997 sp<FakeWindowHandle> window =
3998 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3999 window->setFrame(frameInDisplay, displayTransform);
4000 addWindow(window);
4001
4002 // The following points in logical display space should be inside the window.
4003 static const std::array<vec2, 4> insidePoints{
4004 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4005 for (const auto pointInsideWindow : insidePoints) {
4006 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4007 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004008 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4009 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4010 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004011 window->consumeMotionDown();
4012
Prabir Pradhan678438e2023-04-13 19:32:51 +00004013 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4014 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4015 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004016 window->consumeMotionUp();
4017 }
4018
4019 // The following points in logical display space should be outside the window.
4020 static const std::array<vec2, 5> outsidePoints{
4021 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4022 for (const auto pointOutsideWindow : outsidePoints) {
4023 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4024 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004025 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4026 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4027 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004028
Prabir Pradhan678438e2023-04-13 19:32:51 +00004029 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4030 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4031 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004032 }
4033 window->assertNoEvents();
4034}
4035
4036// Run the precision tests for all rotations.
4037INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4038 InputDispatcherDisplayOrientationFixture,
4039 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4040 ui::ROTATION_270),
4041 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4042 return ftl::enum_string(testParamInfo.param);
4043 });
4044
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004045using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4046 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004047
4048class TransferTouchFixture : public InputDispatcherTest,
4049 public ::testing::WithParamInterface<TransferFunction> {};
4050
4051TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004053
4054 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004055 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004056 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4057 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004058 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004059 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004060 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4061 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004062 sp<FakeWindowHandle> wallpaper =
4063 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4064 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004065 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004066 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004067
4068 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004069 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4070 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004071
Svet Ganov5d3bc372020-01-26 23:11:07 -08004072 // Only the first window should get the down event
4073 firstWindow->consumeMotionDown();
4074 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004075 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004076
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004077 // Transfer touch to the second window
4078 TransferFunction f = GetParam();
4079 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4080 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004081 // The first window gets cancel and the second gets down
4082 firstWindow->consumeMotionCancel();
4083 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004084 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004085
4086 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004087 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4088 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004089 // The first window gets no events and the second gets up
4090 firstWindow->assertNoEvents();
4091 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004092 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004093}
4094
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004095/**
4096 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4097 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4098 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4099 * natural to the user.
4100 * In this test, we are sending a pointer to both spy window and first window. We then try to
4101 * transfer touch to the second window. The dispatcher should identify the first window as the
4102 * one that should lose the gesture, and therefore the action should be to move the gesture from
4103 * the first window to the second.
4104 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4105 * the other API, as well.
4106 */
4107TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4109
4110 // Create a couple of windows + a spy window
4111 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004112 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004113 spyWindow->setTrustedOverlay(true);
4114 spyWindow->setSpy(true);
4115 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004116 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004117 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004118 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004119
4120 // Add the windows to the dispatcher
4121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4122
4123 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004124 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4125 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004126 // Only the first window and spy should get the down event
4127 spyWindow->consumeMotionDown();
4128 firstWindow->consumeMotionDown();
4129
4130 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4131 // if f === 'transferTouch'.
4132 TransferFunction f = GetParam();
4133 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4134 ASSERT_TRUE(success);
4135 // The first window gets cancel and the second gets down
4136 firstWindow->consumeMotionCancel();
4137 secondWindow->consumeMotionDown();
4138
4139 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004140 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4141 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004142 // The first window gets no events and the second+spy get up
4143 firstWindow->assertNoEvents();
4144 spyWindow->consumeMotionUp();
4145 secondWindow->consumeMotionUp();
4146}
4147
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004148TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004150
4151 PointF touchPoint = {10, 10};
4152
4153 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004154 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004155 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4156 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004157 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004158 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004159 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4160 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004161 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004162
4163 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004165
4166 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004167 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4168 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4169 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004170 // Only the first window should get the down event
4171 firstWindow->consumeMotionDown();
4172 secondWindow->assertNoEvents();
4173
4174 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004175 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4176 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004177 // Only the first window should get the pointer down event
4178 firstWindow->consumeMotionPointerDown(1);
4179 secondWindow->assertNoEvents();
4180
4181 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004182 TransferFunction f = GetParam();
4183 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4184 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004185 // The first window gets cancel and the second gets down and pointer down
4186 firstWindow->consumeMotionCancel();
4187 secondWindow->consumeMotionDown();
4188 secondWindow->consumeMotionPointerDown(1);
4189
4190 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004191 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4192 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004193 // The first window gets nothing and the second gets pointer up
4194 firstWindow->assertNoEvents();
4195 secondWindow->consumeMotionPointerUp(1);
4196
4197 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004198 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4199 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004200 // The first window gets nothing and the second gets up
4201 firstWindow->assertNoEvents();
4202 secondWindow->consumeMotionUp();
4203}
4204
Arthur Hungc539dbb2022-12-08 07:45:36 +00004205TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4207
4208 // Create a couple of windows
4209 sp<FakeWindowHandle> firstWindow =
4210 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4211 ADISPLAY_ID_DEFAULT);
4212 firstWindow->setDupTouchToWallpaper(true);
4213 sp<FakeWindowHandle> secondWindow =
4214 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4215 ADISPLAY_ID_DEFAULT);
4216 secondWindow->setDupTouchToWallpaper(true);
4217
4218 sp<FakeWindowHandle> wallpaper1 =
4219 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4220 wallpaper1->setIsWallpaper(true);
4221
4222 sp<FakeWindowHandle> wallpaper2 =
4223 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4224 wallpaper2->setIsWallpaper(true);
4225 // Add the windows to the dispatcher
4226 mDispatcher->setInputWindows(
4227 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4228
4229 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004230 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4231 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004232
4233 // Only the first window should get the down event
4234 firstWindow->consumeMotionDown();
4235 secondWindow->assertNoEvents();
4236 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4237 wallpaper2->assertNoEvents();
4238
4239 // Transfer touch focus to the second window
4240 TransferFunction f = GetParam();
4241 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4242 ASSERT_TRUE(success);
4243
4244 // The first window gets cancel and the second gets down
4245 firstWindow->consumeMotionCancel();
4246 secondWindow->consumeMotionDown();
4247 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4248 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4249
4250 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004251 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4252 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004253 // The first window gets no events and the second gets up
4254 firstWindow->assertNoEvents();
4255 secondWindow->consumeMotionUp();
4256 wallpaper1->assertNoEvents();
4257 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4258}
4259
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004260// For the cases of single pointer touch and two pointers non-split touch, the api's
4261// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4262// for the case where there are multiple pointers split across several windows.
4263INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4264 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004265 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4266 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004267 return dispatcher->transferTouch(destChannelToken,
4268 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004269 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004270 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4271 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004272 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004273 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004274 }));
4275
Svet Ganov5d3bc372020-01-26 23:11:07 -08004276TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004278
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004279 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004280 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4281 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004282 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004283
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004284 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004285 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4286 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004287 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004288
4289 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004291
4292 PointF pointInFirst = {300, 200};
4293 PointF pointInSecond = {300, 600};
4294
4295 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004296 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4297 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4298 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004299 // Only the first window should get the down event
4300 firstWindow->consumeMotionDown();
4301 secondWindow->assertNoEvents();
4302
4303 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004304 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4305 ADISPLAY_ID_DEFAULT,
4306 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004307 // The first window gets a move and the second a down
4308 firstWindow->consumeMotionMove();
4309 secondWindow->consumeMotionDown();
4310
4311 // Transfer touch focus to the second window
4312 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4313 // The first window gets cancel and the new gets pointer down (it already saw down)
4314 firstWindow->consumeMotionCancel();
4315 secondWindow->consumeMotionPointerDown(1);
4316
4317 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004318 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4319 ADISPLAY_ID_DEFAULT,
4320 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004321 // The first window gets nothing and the second gets pointer up
4322 firstWindow->assertNoEvents();
4323 secondWindow->consumeMotionPointerUp(1);
4324
4325 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004326 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4327 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004328 // The first window gets nothing and the second gets up
4329 firstWindow->assertNoEvents();
4330 secondWindow->consumeMotionUp();
4331}
4332
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004333// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4334// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4335// touch is not supported, so the touch should continue on those windows and the transferred-to
4336// window should get nothing.
4337TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4339
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004340 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004341 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4342 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004343 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004344
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004345 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004346 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4347 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004348 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004349
4350 // Add the windows to the dispatcher
4351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4352
4353 PointF pointInFirst = {300, 200};
4354 PointF pointInSecond = {300, 600};
4355
4356 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004357 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4358 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4359 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004360 // Only the first window should get the down event
4361 firstWindow->consumeMotionDown();
4362 secondWindow->assertNoEvents();
4363
4364 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004365 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4366 ADISPLAY_ID_DEFAULT,
4367 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004368 // The first window gets a move and the second a down
4369 firstWindow->consumeMotionMove();
4370 secondWindow->consumeMotionDown();
4371
4372 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004373 const bool transferred =
4374 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004375 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4376 ASSERT_FALSE(transferred);
4377 firstWindow->assertNoEvents();
4378 secondWindow->assertNoEvents();
4379
4380 // The rest of the dispatch should proceed as normal
4381 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004382 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4383 ADISPLAY_ID_DEFAULT,
4384 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004385 // The first window gets MOVE and the second gets pointer up
4386 firstWindow->consumeMotionMove();
4387 secondWindow->consumeMotionUp();
4388
4389 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004390 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4391 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004392 // The first window gets nothing and the second gets up
4393 firstWindow->consumeMotionUp();
4394 secondWindow->assertNoEvents();
4395}
4396
Arthur Hungabbb9d82021-09-01 14:52:30 +00004397// This case will create two windows and one mirrored window on the default display and mirror
4398// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4399// the windows info of second display before default display.
4400TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4401 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4402 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004403 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004404 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004405 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004406 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004407 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004408
4409 sp<FakeWindowHandle> mirrorWindowInPrimary =
4410 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4411 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004412
4413 sp<FakeWindowHandle> firstWindowInSecondary =
4414 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4415 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004416
4417 sp<FakeWindowHandle> secondWindowInSecondary =
4418 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4419 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004420
4421 // Update window info, let it find window handle of second display first.
4422 mDispatcher->setInputWindows(
4423 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4424 {ADISPLAY_ID_DEFAULT,
4425 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4426
4427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4429 {50, 50}))
4430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4431
4432 // Window should receive motion event.
4433 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4434
4435 // Transfer touch focus
4436 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4437 secondWindowInPrimary->getToken()));
4438 // The first window gets cancel.
4439 firstWindowInPrimary->consumeMotionCancel();
4440 secondWindowInPrimary->consumeMotionDown();
4441
4442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4443 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4444 ADISPLAY_ID_DEFAULT, {150, 50}))
4445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4446 firstWindowInPrimary->assertNoEvents();
4447 secondWindowInPrimary->consumeMotionMove();
4448
4449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4450 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4451 {150, 50}))
4452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4453 firstWindowInPrimary->assertNoEvents();
4454 secondWindowInPrimary->consumeMotionUp();
4455}
4456
4457// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4458// 'transferTouch' api.
4459TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4460 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4461 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004462 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004463 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004464 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004465 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004466 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004467
4468 sp<FakeWindowHandle> mirrorWindowInPrimary =
4469 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4470 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004471
4472 sp<FakeWindowHandle> firstWindowInSecondary =
4473 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4474 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004475
4476 sp<FakeWindowHandle> secondWindowInSecondary =
4477 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4478 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004479
4480 // Update window info, let it find window handle of second display first.
4481 mDispatcher->setInputWindows(
4482 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4483 {ADISPLAY_ID_DEFAULT,
4484 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4485
4486 // Touch on second display.
4487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4488 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4490
4491 // Window should receive motion event.
4492 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4493
4494 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004495 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004496
4497 // The first window gets cancel.
4498 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4499 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4500
4501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4502 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4503 SECOND_DISPLAY_ID, {150, 50}))
4504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4505 firstWindowInPrimary->assertNoEvents();
4506 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4507
4508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4509 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4511 firstWindowInPrimary->assertNoEvents();
4512 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4513}
4514
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004515TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004516 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004517 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4518 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004519
Vishnu Nair47074b82020-08-14 11:54:47 -07004520 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004521 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004522 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004523
4524 window->consumeFocusEvent(true);
4525
Prabir Pradhan678438e2023-04-13 19:32:51 +00004526 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004527
4528 // Window should receive key down event.
4529 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4530}
4531
4532TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004534 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4535 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004536
Arthur Hung72d8dc32020-03-28 00:48:39 +00004537 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004538
Prabir Pradhan678438e2023-04-13 19:32:51 +00004539 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004540 mDispatcher->waitForIdle();
4541
4542 window->assertNoEvents();
4543}
4544
4545// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4546TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004548 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4549 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004550
Arthur Hung72d8dc32020-03-28 00:48:39 +00004551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004552
4553 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004554 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004555 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004558
4559 // Window should receive only the motion event
4560 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4561 window->assertNoEvents(); // Key event or focus event will not be received
4562}
4563
arthurhungea3f4fc2020-12-21 23:18:53 +08004564TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4565 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4566
arthurhungea3f4fc2020-12-21 23:18:53 +08004567 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004568 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4569 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004570 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004571
arthurhungea3f4fc2020-12-21 23:18:53 +08004572 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004573 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4574 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004575 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004576
4577 // Add the windows to the dispatcher
4578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4579
4580 PointF pointInFirst = {300, 200};
4581 PointF pointInSecond = {300, 600};
4582
4583 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004584 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4585 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4586 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004587 // Only the first window should get the down event
4588 firstWindow->consumeMotionDown();
4589 secondWindow->assertNoEvents();
4590
4591 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004592 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4593 ADISPLAY_ID_DEFAULT,
4594 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004595 // The first window gets a move and the second a down
4596 firstWindow->consumeMotionMove();
4597 secondWindow->consumeMotionDown();
4598
4599 // Send pointer cancel to the second window
4600 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004601 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004602 {pointInFirst, pointInSecond});
4603 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004604 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004605 // The first window gets move and the second gets cancel.
4606 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4607 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4608
4609 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004610 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4611 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004612 // The first window gets up and the second gets nothing.
4613 firstWindow->consumeMotionUp();
4614 secondWindow->assertNoEvents();
4615}
4616
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004617TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4619
4620 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004621 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4623 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4624 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4625 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4626
Harry Cutts33476232023-01-30 19:57:29 +00004627 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004628 window->assertNoEvents();
4629 mDispatcher->waitForIdle();
4630}
4631
chaviwd1c23182019-12-20 18:44:56 -08004632class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004633public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004634 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004635 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004636 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004637 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004638 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004639 }
4640
chaviwd1c23182019-12-20 18:44:56 -08004641 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4642
4643 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004644 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4645 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004646 }
4647
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004648 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4649
4650 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4651
chaviwd1c23182019-12-20 18:44:56 -08004652 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004653 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004654 expectedDisplayId, expectedFlags);
4655 }
4656
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004657 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004658 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004659 expectedDisplayId, expectedFlags);
4660 }
4661
chaviwd1c23182019-12-20 18:44:56 -08004662 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004663 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004664 expectedDisplayId, expectedFlags);
4665 }
4666
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004667 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004668 mInputReceiver->consumeMotionEvent(
4669 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4670 WithDisplayId(expectedDisplayId),
4671 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004672 }
4673
Arthur Hungfbfa5722021-11-16 02:45:54 +00004674 void consumeMotionPointerDown(int32_t pointerIdx) {
4675 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4676 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004677 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004678 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004679 }
4680
Evan Rosky84f07f02021-04-16 10:42:42 -07004681 MotionEvent* consumeMotion() {
4682 InputEvent* event = mInputReceiver->consume();
4683 if (!event) {
4684 ADD_FAILURE() << "No event was produced";
4685 return nullptr;
4686 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004687 if (event->getType() != InputEventType::MOTION) {
4688 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004689 return nullptr;
4690 }
4691 return static_cast<MotionEvent*>(event);
4692 }
4693
chaviwd1c23182019-12-20 18:44:56 -08004694 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4695
4696private:
4697 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004698};
4699
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004700using InputDispatcherMonitorTest = InputDispatcherTest;
4701
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004702/**
4703 * Two entities that receive touch: A window, and a global monitor.
4704 * The touch goes to the window, and then the window disappears.
4705 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4706 * for the monitor, as well.
4707 * 1. foregroundWindow
4708 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4709 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004710TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4712 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004713 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004714
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004715 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004716
4717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4719 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4720 {100, 200}))
4721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4722
4723 // Both the foreground window and the global monitor should receive the touch down
4724 window->consumeMotionDown();
4725 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4726
4727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4728 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4729 ADISPLAY_ID_DEFAULT, {110, 200}))
4730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4731
4732 window->consumeMotionMove();
4733 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4734
4735 // Now the foreground window goes away
4736 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4737 window->consumeMotionCancel();
4738 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4739
4740 // If more events come in, there will be no more foreground window to send them to. This will
4741 // cause a cancel for the monitor, as well.
4742 ASSERT_EQ(InputEventInjectionResult::FAILED,
4743 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4744 ADISPLAY_ID_DEFAULT, {120, 200}))
4745 << "Injection should fail because the window was removed";
4746 window->assertNoEvents();
4747 // Global monitor now gets the cancel
4748 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4749}
4750
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004751TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004753 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4754 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004755 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004756
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004757 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004758
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004760 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004762 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004763 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004764}
4765
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004766TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4767 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004768
Chris Yea209fde2020-07-22 13:54:51 -07004769 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004770 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4771 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004772 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004773
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004775 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004777 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004778 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004779
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004780 // Pilfer pointers from the monitor.
4781 // This should not do anything and the window should continue to receive events.
4782 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004783
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004785 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4786 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004788
4789 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4790 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004791}
4792
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004793TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004795 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4796 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004797 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4798 window->setWindowOffset(20, 40);
4799 window->setWindowTransform(0, 1, -1, 0);
4800
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004801 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004802
4803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4804 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4806 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4807 MotionEvent* event = monitor.consumeMotion();
4808 // Even though window has transform, gesture monitor must not.
4809 ASSERT_EQ(ui::Transform(), event->getTransform());
4810}
4811
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004812TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004814 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004815
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004816 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004818 << "Injection should fail if there is a monitor, but no touchable window";
4819 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004820}
4821
chaviw81e2bb92019-12-18 15:03:51 -08004822TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004824 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4825 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004826
Arthur Hung72d8dc32020-03-28 00:48:39 +00004827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004828
4829 NotifyMotionArgs motionArgs =
4830 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4831 ADISPLAY_ID_DEFAULT);
4832
Prabir Pradhan678438e2023-04-13 19:32:51 +00004833 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08004834 // Window should receive motion down event.
4835 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4836
4837 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004838 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004839 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4840 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4841 motionArgs.pointerCoords[0].getX() - 10);
4842
Prabir Pradhan678438e2023-04-13 19:32:51 +00004843 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004844 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004845 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004846}
4847
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004848/**
4849 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
4850 * the device default right away. In the test scenario, we check both the default value,
4851 * and the action of enabling / disabling.
4852 */
4853TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07004854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4856 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08004857 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004858
4859 // Set focused application.
4860 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004861 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004862
4863 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00004864 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004865 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004866 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004867
4868 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004869 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004870 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004871 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004872
4873 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004874 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004875 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004876 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07004877 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004879 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004880 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004881
4882 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004883 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004885 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004886
4887 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004888 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004889 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004890 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07004891 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004893 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004894 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004895
4896 window->assertNoEvents();
4897}
4898
Gang Wange9087892020-01-07 12:17:14 -05004899TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004901 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4902 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05004903
4904 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004905 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05004906
Arthur Hung72d8dc32020-03-28 00:48:39 +00004907 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004908 setFocusedWindow(window);
4909
Harry Cutts33476232023-01-30 19:57:29 +00004910 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05004911
Prabir Pradhan678438e2023-04-13 19:32:51 +00004912 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4913 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05004914
4915 InputEvent* event = window->consume();
4916 ASSERT_NE(event, nullptr);
4917
4918 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4919 ASSERT_NE(verified, nullptr);
4920 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
4921
4922 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
4923 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
4924 ASSERT_EQ(keyArgs.source, verified->source);
4925 ASSERT_EQ(keyArgs.displayId, verified->displayId);
4926
4927 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
4928
4929 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05004930 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004931 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05004932 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
4933 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
4934 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
4935 ASSERT_EQ(0, verifiedKey.repeatCount);
4936}
4937
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004938TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004940 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4941 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004942
4943 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4944
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004945 ui::Transform transform;
4946 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4947
4948 gui::DisplayInfo displayInfo;
4949 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
4950 displayInfo.transform = transform;
4951
4952 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004953
Prabir Pradhan678438e2023-04-13 19:32:51 +00004954 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004955 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4956 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004957 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004958
4959 InputEvent* event = window->consume();
4960 ASSERT_NE(event, nullptr);
4961
4962 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4963 ASSERT_NE(verified, nullptr);
4964 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
4965
4966 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
4967 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
4968 EXPECT_EQ(motionArgs.source, verified->source);
4969 EXPECT_EQ(motionArgs.displayId, verified->displayId);
4970
4971 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
4972
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004973 const vec2 rawXY =
4974 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
4975 motionArgs.pointerCoords[0].getXYValue());
4976 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
4977 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004978 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004979 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004980 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004981 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
4982 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
4983}
4984
chaviw09c8d2d2020-08-24 15:48:26 -07004985/**
4986 * Ensure that separate calls to sign the same data are generating the same key.
4987 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
4988 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
4989 * tests.
4990 */
4991TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
4992 KeyEvent event = getTestKeyEvent();
4993 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
4994
4995 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
4996 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
4997 ASSERT_EQ(hmac1, hmac2);
4998}
4999
5000/**
5001 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5002 */
5003TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5004 KeyEvent event = getTestKeyEvent();
5005 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5006 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5007
5008 verifiedEvent.deviceId += 1;
5009 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5010
5011 verifiedEvent.source += 1;
5012 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5013
5014 verifiedEvent.eventTimeNanos += 1;
5015 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5016
5017 verifiedEvent.displayId += 1;
5018 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5019
5020 verifiedEvent.action += 1;
5021 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5022
5023 verifiedEvent.downTimeNanos += 1;
5024 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5025
5026 verifiedEvent.flags += 1;
5027 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5028
5029 verifiedEvent.keyCode += 1;
5030 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5031
5032 verifiedEvent.scanCode += 1;
5033 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5034
5035 verifiedEvent.metaState += 1;
5036 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5037
5038 verifiedEvent.repeatCount += 1;
5039 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5040}
5041
Vishnu Nair958da932020-08-21 17:12:37 -07005042TEST_F(InputDispatcherTest, SetFocusedWindow) {
5043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5044 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005045 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005046 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005047 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005048 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5049
5050 // Top window is also focusable but is not granted focus.
5051 windowTop->setFocusable(true);
5052 windowSecond->setFocusable(true);
5053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5054 setFocusedWindow(windowSecond);
5055
5056 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5058 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005059
5060 // Focused window should receive event.
5061 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5062 windowTop->assertNoEvents();
5063}
5064
5065TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5067 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005068 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005069 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5070
5071 window->setFocusable(true);
5072 // Release channel for window is no longer valid.
5073 window->releaseChannel();
5074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5075 setFocusedWindow(window);
5076
5077 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005078 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5079 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005080
5081 // window channel is invalid, so it should not receive any input event.
5082 window->assertNoEvents();
5083}
5084
5085TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5087 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005088 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005089 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005090 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5091
Vishnu Nair958da932020-08-21 17:12:37 -07005092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5093 setFocusedWindow(window);
5094
5095 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005096 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5097 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005098
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005099 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005100 window->assertNoEvents();
5101}
5102
5103TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5105 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005106 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005107 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005108 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5110
5111 windowTop->setFocusable(true);
5112 windowSecond->setFocusable(true);
5113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5114 setFocusedWindow(windowTop);
5115 windowTop->consumeFocusEvent(true);
5116
Chavi Weingarten847e8512023-03-29 00:26:09 +00005117 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5118 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005119 windowSecond->consumeFocusEvent(true);
5120 windowTop->consumeFocusEvent(false);
5121
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5123 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005124
5125 // Focused window should receive event.
5126 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5127}
5128
Chavi Weingarten847e8512023-03-29 00:26:09 +00005129TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5131 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005132 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005133 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005134 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005135 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5136
5137 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005138 windowSecond->setFocusable(false);
5139 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005141 setFocusedWindow(windowTop);
5142 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005143
Chavi Weingarten847e8512023-03-29 00:26:09 +00005144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5145 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005146
5147 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005148 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005149 windowSecond->assertNoEvents();
5150}
5151
5152TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5153 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5154 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005155 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005156 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005157 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5158 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5160
5161 window->setFocusable(true);
5162 previousFocusedWindow->setFocusable(true);
5163 window->setVisible(false);
5164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5165 setFocusedWindow(previousFocusedWindow);
5166 previousFocusedWindow->consumeFocusEvent(true);
5167
5168 // Requesting focus on invisible window takes focus from currently focused window.
5169 setFocusedWindow(window);
5170 previousFocusedWindow->consumeFocusEvent(false);
5171
5172 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005174 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5175 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005176
5177 // Window does not get focus event or key down.
5178 window->assertNoEvents();
5179
5180 // Window becomes visible.
5181 window->setVisible(true);
5182 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5183
5184 // Window receives focus event.
5185 window->consumeFocusEvent(true);
5186 // Focused window receives key down.
5187 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5188}
5189
Vishnu Nair599f1412021-06-21 10:39:58 -07005190TEST_F(InputDispatcherTest, DisplayRemoved) {
5191 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5192 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005193 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005194 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5195
5196 // window is granted focus.
5197 window->setFocusable(true);
5198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5199 setFocusedWindow(window);
5200 window->consumeFocusEvent(true);
5201
5202 // When a display is removed window loses focus.
5203 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5204 window->consumeFocusEvent(false);
5205}
5206
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005207/**
5208 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5209 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5210 * of the 'slipperyEnterWindow'.
5211 *
5212 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5213 * a way so that the touched location is no longer covered by the top window.
5214 *
5215 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5216 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5217 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5218 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5219 * with ACTION_DOWN).
5220 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5221 * window moved itself away from the touched location and had Flag::SLIPPERY.
5222 *
5223 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5224 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5225 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5226 *
5227 * In this test, we ensure that the event received by the bottom window has
5228 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5229 */
5230TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005231 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5232 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005233
5234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5235 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5236
5237 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005238 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005239 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005240 // Make sure this one overlaps the bottom window
5241 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5242 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5243 // one. Windows with the same owner are not considered to be occluding each other.
5244 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5245
5246 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005247 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005248 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5249
5250 mDispatcher->setInputWindows(
5251 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5252
5253 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005254 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5255 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5256 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005257 slipperyExitWindow->consumeMotionDown();
5258 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5259 mDispatcher->setInputWindows(
5260 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5261
Prabir Pradhan678438e2023-04-13 19:32:51 +00005262 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5263 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5264 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005265
5266 slipperyExitWindow->consumeMotionCancel();
5267
5268 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5269 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5270}
5271
Garfield Tan1c7bc862020-01-28 13:24:04 -08005272class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5273protected:
5274 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5275 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5276
Chris Yea209fde2020-07-22 13:54:51 -07005277 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005278 sp<FakeWindowHandle> mWindow;
5279
5280 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005281 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005282 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005283 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005284 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005285 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5286 ASSERT_EQ(OK, mDispatcher->start());
5287
5288 setUpWindow();
5289 }
5290
5291 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005292 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005293 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005294
Vishnu Nair47074b82020-08-14 11:54:47 -07005295 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005297 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005298 mWindow->consumeFocusEvent(true);
5299 }
5300
Chris Ye2ad95392020-09-01 13:44:44 -07005301 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005302 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005303 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005304 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005305 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005306
5307 // Window should receive key down event.
5308 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5309 }
5310
5311 void expectKeyRepeatOnce(int32_t repeatCount) {
5312 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5313 InputEvent* repeatEvent = mWindow->consume();
5314 ASSERT_NE(nullptr, repeatEvent);
5315
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005316 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005317
5318 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5319 uint32_t eventAction = repeatKeyEvent->getAction();
5320 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5321 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5322 }
5323
Chris Ye2ad95392020-09-01 13:44:44 -07005324 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005325 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005326 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005327 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005328 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005329
5330 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005331 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005332 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005333 }
5334};
5335
5336TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005337 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005338 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5339 expectKeyRepeatOnce(repeatCount);
5340 }
5341}
5342
5343TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005344 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005345 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5346 expectKeyRepeatOnce(repeatCount);
5347 }
Harry Cutts33476232023-01-30 19:57:29 +00005348 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005349 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005350 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5351 expectKeyRepeatOnce(repeatCount);
5352 }
5353}
5354
5355TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005356 sendAndConsumeKeyDown(/*deviceId=*/1);
5357 expectKeyRepeatOnce(/*repeatCount=*/1);
5358 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005359 mWindow->assertNoEvents();
5360}
5361
5362TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005363 sendAndConsumeKeyDown(/*deviceId=*/1);
5364 expectKeyRepeatOnce(/*repeatCount=*/1);
5365 sendAndConsumeKeyDown(/*deviceId=*/2);
5366 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005367 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005368 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005369 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005370 expectKeyRepeatOnce(/*repeatCount=*/2);
5371 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005372 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005373 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005374 mWindow->assertNoEvents();
5375}
5376
5377TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005378 sendAndConsumeKeyDown(/*deviceId=*/1);
5379 expectKeyRepeatOnce(/*repeatCount=*/1);
5380 sendAndConsumeKeyDown(/*deviceId=*/2);
5381 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005382 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005383 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005384 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005385 mWindow->assertNoEvents();
5386}
5387
liushenxiang42232912021-05-21 20:24:09 +08005388TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5389 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005390 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005391 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005392 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5393 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5394 mWindow->assertNoEvents();
5395}
5396
Garfield Tan1c7bc862020-01-28 13:24:04 -08005397TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005398 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005399 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005400 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5401 InputEvent* repeatEvent = mWindow->consume();
5402 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5403 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5404 IdGenerator::getSource(repeatEvent->getId()));
5405 }
5406}
5407
5408TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005409 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005410 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005411
5412 std::unordered_set<int32_t> idSet;
5413 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5414 InputEvent* repeatEvent = mWindow->consume();
5415 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5416 int32_t id = repeatEvent->getId();
5417 EXPECT_EQ(idSet.end(), idSet.find(id));
5418 idSet.insert(id);
5419 }
5420}
5421
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005422/* Test InputDispatcher for MultiDisplay */
5423class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5424public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005425 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005426 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005427
Chris Yea209fde2020-07-22 13:54:51 -07005428 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005429 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005430 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005431
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005432 // Set focus window for primary display, but focused display would be second one.
5433 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005434 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005435 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005436 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005437 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005438
Chris Yea209fde2020-07-22 13:54:51 -07005439 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005440 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005441 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005442 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005443 // Set focus display to second one.
5444 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5445 // Set focus window for second display.
5446 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005447 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005448 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005449 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005450 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005451 }
5452
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005453 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005454 InputDispatcherTest::TearDown();
5455
Chris Yea209fde2020-07-22 13:54:51 -07005456 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005457 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005458 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005459 windowInSecondary.clear();
5460 }
5461
5462protected:
Chris Yea209fde2020-07-22 13:54:51 -07005463 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005464 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005465 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005466 sp<FakeWindowHandle> windowInSecondary;
5467};
5468
5469TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5470 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5472 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5473 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005474 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005475 windowInSecondary->assertNoEvents();
5476
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005477 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5479 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5480 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005481 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005482 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005483}
5484
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005485TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005486 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5488 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005489 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005490 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005491 windowInSecondary->assertNoEvents();
5492
5493 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005495 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005496 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005497 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005498
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005499 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005500 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005502 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005503 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005504 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005505
5506 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005507 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005508 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005509 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005510 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005511 windowInSecondary->assertNoEvents();
5512}
5513
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005514// Test per-display input monitors for motion event.
5515TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005516 FakeMonitorReceiver monitorInPrimary =
5517 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5518 FakeMonitorReceiver monitorInSecondary =
5519 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005520
5521 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5523 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005525 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005526 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005527 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005528 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005529
5530 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5532 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005534 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005535 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005536 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005537 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005538
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005539 // Lift up the touch from the second display
5540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5541 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5543 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5544 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5545
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005546 // Test inject a non-pointer motion event.
5547 // If specific a display, it will dispatch to the focused window of particular display,
5548 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5550 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005552 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005553 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005554 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005555 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005556}
5557
5558// Test per-display input monitors for key event.
5559TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005560 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005561 FakeMonitorReceiver monitorInPrimary =
5562 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5563 FakeMonitorReceiver monitorInSecondary =
5564 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005565
5566 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5568 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005569 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005570 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005571 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005572 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005573}
5574
Vishnu Nair958da932020-08-21 17:12:37 -07005575TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5576 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005577 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005578 secondWindowInPrimary->setFocusable(true);
5579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5580 setFocusedWindow(secondWindowInPrimary);
5581 windowInPrimary->consumeFocusEvent(false);
5582 secondWindowInPrimary->consumeFocusEvent(true);
5583
5584 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5586 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005587 windowInPrimary->assertNoEvents();
5588 windowInSecondary->assertNoEvents();
5589 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5590}
5591
Arthur Hungdfd528e2021-12-08 13:23:04 +00005592TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5593 FakeMonitorReceiver monitorInPrimary =
5594 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5595 FakeMonitorReceiver monitorInSecondary =
5596 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5597
5598 // Test touch down on primary display.
5599 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5600 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5601 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5602 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5603 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5604
5605 // Test touch down on second display.
5606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5607 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5609 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5610 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5611
5612 // Trigger cancel touch.
5613 mDispatcher->cancelCurrentTouch();
5614 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5615 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5616 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5617 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5618
5619 // Test inject a move motion event, no window/monitor should receive the event.
5620 ASSERT_EQ(InputEventInjectionResult::FAILED,
5621 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5622 ADISPLAY_ID_DEFAULT, {110, 200}))
5623 << "Inject motion event should return InputEventInjectionResult::FAILED";
5624 windowInPrimary->assertNoEvents();
5625 monitorInPrimary.assertNoEvents();
5626
5627 ASSERT_EQ(InputEventInjectionResult::FAILED,
5628 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5629 SECOND_DISPLAY_ID, {110, 200}))
5630 << "Inject motion event should return InputEventInjectionResult::FAILED";
5631 windowInSecondary->assertNoEvents();
5632 monitorInSecondary.assertNoEvents();
5633}
5634
Jackal Guof9696682018-10-05 12:23:23 +08005635class InputFilterTest : public InputDispatcherTest {
5636protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005637 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5638 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005639 NotifyMotionArgs motionArgs;
5640
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005641 motionArgs =
5642 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005643 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005644 motionArgs =
5645 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005646 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005647 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005648 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005649 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5650 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005651 } else {
5652 mFakePolicy->assertFilterInputEventWasNotCalled();
5653 }
5654 }
5655
5656 void testNotifyKey(bool expectToBeFiltered) {
5657 NotifyKeyArgs keyArgs;
5658
5659 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005660 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005661 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005662 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005663 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005664
5665 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005666 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005667 } else {
5668 mFakePolicy->assertFilterInputEventWasNotCalled();
5669 }
5670 }
5671};
5672
5673// Test InputFilter for MotionEvent
5674TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5675 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5676 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5677 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5678
5679 // Enable InputFilter
5680 mDispatcher->setInputFilterEnabled(true);
5681 // Test touch on both primary and second display, and check if both events are filtered.
5682 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5683 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5684
5685 // Disable InputFilter
5686 mDispatcher->setInputFilterEnabled(false);
5687 // Test touch on both primary and second display, and check if both events aren't filtered.
5688 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5689 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5690}
5691
5692// Test InputFilter for KeyEvent
5693TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5694 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5695 testNotifyKey(/*expectToBeFiltered*/ false);
5696
5697 // Enable InputFilter
5698 mDispatcher->setInputFilterEnabled(true);
5699 // Send a key event, and check if it is filtered.
5700 testNotifyKey(/*expectToBeFiltered*/ true);
5701
5702 // Disable InputFilter
5703 mDispatcher->setInputFilterEnabled(false);
5704 // Send a key event, and check if it isn't filtered.
5705 testNotifyKey(/*expectToBeFiltered*/ false);
5706}
5707
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005708// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5709// logical display coordinate space.
5710TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5711 ui::Transform firstDisplayTransform;
5712 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5713 ui::Transform secondDisplayTransform;
5714 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5715
5716 std::vector<gui::DisplayInfo> displayInfos(2);
5717 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5718 displayInfos[0].transform = firstDisplayTransform;
5719 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5720 displayInfos[1].transform = secondDisplayTransform;
5721
5722 mDispatcher->onWindowInfosChanged({}, displayInfos);
5723
5724 // Enable InputFilter
5725 mDispatcher->setInputFilterEnabled(true);
5726
5727 // Ensure the correct transforms are used for the displays.
5728 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5729 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5730}
5731
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005732class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5733protected:
5734 virtual void SetUp() override {
5735 InputDispatcherTest::SetUp();
5736
5737 /**
5738 * We don't need to enable input filter to test the injected event policy, but we enabled it
5739 * here to make the tests more realistic, since this policy only matters when inputfilter is
5740 * on.
5741 */
5742 mDispatcher->setInputFilterEnabled(true);
5743
5744 std::shared_ptr<InputApplicationHandle> application =
5745 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005746 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5747 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005748
5749 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5750 mWindow->setFocusable(true);
5751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5752 setFocusedWindow(mWindow);
5753 mWindow->consumeFocusEvent(true);
5754 }
5755
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005756 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5757 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005758 KeyEvent event;
5759
5760 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5761 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5762 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005763 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005764 const int32_t additionalPolicyFlags =
5765 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005767 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005768 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5769 policyFlags | additionalPolicyFlags));
5770
5771 InputEvent* received = mWindow->consume();
5772 ASSERT_NE(nullptr, received);
5773 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005774 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005775 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5776 ASSERT_EQ(flags, keyEvent.getFlags());
5777 }
5778
5779 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5780 int32_t flags) {
5781 MotionEvent event;
5782 PointerProperties pointerProperties[1];
5783 PointerCoords pointerCoords[1];
5784 pointerProperties[0].clear();
5785 pointerProperties[0].id = 0;
5786 pointerCoords[0].clear();
5787 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5788 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5789
5790 ui::Transform identityTransform;
5791 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5792 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5793 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5794 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5795 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005796 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005797 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005798 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5799
5800 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005802 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005803 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5804 policyFlags | additionalPolicyFlags));
5805
5806 InputEvent* received = mWindow->consume();
5807 ASSERT_NE(nullptr, received);
5808 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005809 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005810 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5811 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005812 }
5813
5814private:
5815 sp<FakeWindowHandle> mWindow;
5816};
5817
5818TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005819 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5820 // filter. Without it, the event will no different from a regularly injected event, and the
5821 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005822 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5823 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005824}
5825
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005826TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005827 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005828 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005829 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5830}
5831
5832TEST_F(InputFilterInjectionPolicyTest,
5833 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5834 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005835 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005836 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005837}
5838
5839TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005840 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5841 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005842}
5843
chaviwfd6d3512019-03-25 13:23:49 -07005844class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005845 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005846 InputDispatcherTest::SetUp();
5847
Chris Yea209fde2020-07-22 13:54:51 -07005848 std::shared_ptr<FakeApplicationHandle> application =
5849 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005850 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005851 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005852 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07005853
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005854 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005855 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005856 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07005857
5858 // Set focused application.
5859 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005860 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07005861
5862 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005864 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005865 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07005866 }
5867
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005868 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07005869 InputDispatcherTest::TearDown();
5870
5871 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005872 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07005873 }
5874
5875protected:
5876 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005877 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005878 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07005879};
5880
5881// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5882// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
5883// the onPointerDownOutsideFocus callback.
5884TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005886 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5887 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005888 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005889 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005890
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005891 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07005892 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
5893}
5894
5895// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
5896// DOWN on the window that doesn't have focus. Ensure no window received the
5897// onPointerDownOutsideFocus callback.
5898TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005899 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005900 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005902 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005903
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005904 ASSERT_TRUE(mDispatcher->waitForIdle());
5905 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005906}
5907
5908// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
5909// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
5910TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5912 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005914 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005915
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005916 ASSERT_TRUE(mDispatcher->waitForIdle());
5917 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005918}
5919
5920// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5921// DOWN on the window that already has focus. Ensure no window received the
5922// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005923TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005925 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005926 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005928 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005929
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005930 ASSERT_TRUE(mDispatcher->waitForIdle());
5931 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005932}
5933
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005934// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
5935// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
5936TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
5937 const MotionEvent event =
5938 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5939 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005940 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005941 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
5942 .build();
5943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
5944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5945 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5946
5947 ASSERT_TRUE(mDispatcher->waitForIdle());
5948 mFakePolicy->assertOnPointerDownWasNotCalled();
5949 // Ensure that the unfocused window did not receive any FOCUS events.
5950 mUnfocusedWindow->assertNoEvents();
5951}
5952
chaviwaf87b3e2019-10-01 16:59:28 -07005953// These tests ensures we can send touch events to a single client when there are multiple input
5954// windows that point to the same client token.
5955class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
5956 virtual void SetUp() override {
5957 InputDispatcherTest::SetUp();
5958
Chris Yea209fde2020-07-22 13:54:51 -07005959 std::shared_ptr<FakeApplicationHandle> application =
5960 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005961 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
5962 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07005963 mWindow1->setFrame(Rect(0, 0, 100, 100));
5964
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005965 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
5966 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07005967 mWindow2->setFrame(Rect(100, 100, 200, 200));
5968
Arthur Hung72d8dc32020-03-28 00:48:39 +00005969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07005970 }
5971
5972protected:
5973 sp<FakeWindowHandle> mWindow1;
5974 sp<FakeWindowHandle> mWindow2;
5975
5976 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05005977 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07005978 vec2 vals = windowInfo->transform.transform(point.x, point.y);
5979 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07005980 }
5981
5982 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
5983 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005984 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07005985 InputEvent* event = window->consume();
5986
5987 ASSERT_NE(nullptr, event) << name.c_str()
5988 << ": consumer should have returned non-NULL event.";
5989
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005990 ASSERT_EQ(InputEventType::MOTION, event->getType())
5991 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07005992
5993 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005994 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08005995 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07005996
5997 for (size_t i = 0; i < points.size(); i++) {
5998 float expectedX = points[i].x;
5999 float expectedY = points[i].y;
6000
6001 EXPECT_EQ(expectedX, motionEvent.getX(i))
6002 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6003 << ", got " << motionEvent.getX(i);
6004 EXPECT_EQ(expectedY, motionEvent.getY(i))
6005 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6006 << ", got " << motionEvent.getY(i);
6007 }
6008 }
chaviw9eaa22c2020-07-01 16:21:27 -07006009
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006010 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006011 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006012 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6013 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006014
6015 // Always consume from window1 since it's the window that has the InputReceiver
6016 consumeMotionEvent(mWindow1, action, expectedPoints);
6017 }
chaviwaf87b3e2019-10-01 16:59:28 -07006018};
6019
6020TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6021 // Touch Window 1
6022 PointF touchedPoint = {10, 10};
6023 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006024 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006025
6026 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006027 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006028
6029 // Touch Window 2
6030 touchedPoint = {150, 150};
6031 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006032 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006033}
6034
chaviw9eaa22c2020-07-01 16:21:27 -07006035TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6036 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006037 mWindow2->setWindowScale(0.5f, 0.5f);
6038
6039 // Touch Window 1
6040 PointF touchedPoint = {10, 10};
6041 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006042 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006043 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006044 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006045
6046 // Touch Window 2
6047 touchedPoint = {150, 150};
6048 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006049 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6050 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006051
chaviw9eaa22c2020-07-01 16:21:27 -07006052 // Update the transform so rotation is set
6053 mWindow2->setWindowTransform(0, -1, 1, 0);
6054 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6055 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006056}
6057
chaviw9eaa22c2020-07-01 16:21:27 -07006058TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006059 mWindow2->setWindowScale(0.5f, 0.5f);
6060
6061 // Touch Window 1
6062 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6063 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006064 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006065
6066 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006067 touchedPoints.push_back(PointF{150, 150});
6068 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006069 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006070
chaviw9eaa22c2020-07-01 16:21:27 -07006071 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006072 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006073 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006074
chaviw9eaa22c2020-07-01 16:21:27 -07006075 // Update the transform so rotation is set for Window 2
6076 mWindow2->setWindowTransform(0, -1, 1, 0);
6077 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006078 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006079}
6080
chaviw9eaa22c2020-07-01 16:21:27 -07006081TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006082 mWindow2->setWindowScale(0.5f, 0.5f);
6083
6084 // Touch Window 1
6085 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6086 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006087 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006088
6089 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006090 touchedPoints.push_back(PointF{150, 150});
6091 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006092
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006093 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006094
6095 // Move both windows
6096 touchedPoints = {{20, 20}, {175, 175}};
6097 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6098 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6099
chaviw9eaa22c2020-07-01 16:21:27 -07006100 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006101
chaviw9eaa22c2020-07-01 16:21:27 -07006102 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006103 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006104 expectedPoints.pop_back();
6105
6106 // Touch Window 2
6107 mWindow2->setWindowTransform(0, -1, 1, 0);
6108 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006109 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006110
6111 // Move both windows
6112 touchedPoints = {{20, 20}, {175, 175}};
6113 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6114 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6115
6116 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006117}
6118
6119TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6120 mWindow1->setWindowScale(0.5f, 0.5f);
6121
6122 // Touch Window 1
6123 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6124 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006125 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006126
6127 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006128 touchedPoints.push_back(PointF{150, 150});
6129 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006130
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006131 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006132
6133 // Move both windows
6134 touchedPoints = {{20, 20}, {175, 175}};
6135 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6136 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6137
chaviw9eaa22c2020-07-01 16:21:27 -07006138 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006139}
6140
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006141class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6142 virtual void SetUp() override {
6143 InputDispatcherTest::SetUp();
6144
Chris Yea209fde2020-07-22 13:54:51 -07006145 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006146 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006147 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6148 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006149 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006150 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006151 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006152
6153 // Set focused application.
6154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6155
6156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006157 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006158 mWindow->consumeFocusEvent(true);
6159 }
6160
6161 virtual void TearDown() override {
6162 InputDispatcherTest::TearDown();
6163 mWindow.clear();
6164 }
6165
6166protected:
Chris Yea209fde2020-07-22 13:54:51 -07006167 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006168 sp<FakeWindowHandle> mWindow;
6169 static constexpr PointF WINDOW_LOCATION = {20, 20};
6170
6171 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006173 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6174 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006176 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6177 WINDOW_LOCATION));
6178 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006179
6180 sp<FakeWindowHandle> addSpyWindow() {
6181 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006182 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006183 spy->setTrustedOverlay(true);
6184 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006185 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006186 spy->setDispatchingTimeout(30ms);
6187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6188 return spy;
6189 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006190};
6191
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006192// Send a tap and respond, which should not cause an ANR.
6193TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6194 tapOnWindow();
6195 mWindow->consumeMotionDown();
6196 mWindow->consumeMotionUp();
6197 ASSERT_TRUE(mDispatcher->waitForIdle());
6198 mFakePolicy->assertNotifyAnrWasNotCalled();
6199}
6200
6201// Send a regular key and respond, which should not cause an ANR.
6202TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006204 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6205 ASSERT_TRUE(mDispatcher->waitForIdle());
6206 mFakePolicy->assertNotifyAnrWasNotCalled();
6207}
6208
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006209TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6210 mWindow->setFocusable(false);
6211 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6212 mWindow->consumeFocusEvent(false);
6213
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006214 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006215 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6216 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6217 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006219 // Key will not go to window because we have no focused window.
6220 // The 'no focused window' ANR timer should start instead.
6221
6222 // Now, the focused application goes away.
6223 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6224 // The key should get dropped and there should be no ANR.
6225
6226 ASSERT_TRUE(mDispatcher->waitForIdle());
6227 mFakePolicy->assertNotifyAnrWasNotCalled();
6228}
6229
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006230// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006231// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6232// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006233TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006235 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6236 WINDOW_LOCATION));
6237
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006238 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6239 ASSERT_TRUE(sequenceNum);
6240 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006241 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006242
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006243 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006244 mWindow->consumeMotionEvent(
6245 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006246 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006247 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006248}
6249
6250// Send a key to the app and have the app not respond right away.
6251TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6252 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006254 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6255 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006256 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006257 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006258 ASSERT_TRUE(mDispatcher->waitForIdle());
6259}
6260
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006261// We have a focused application, but no focused window
6262TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006263 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006264 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6265 mWindow->consumeFocusEvent(false);
6266
6267 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006269 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6270 WINDOW_LOCATION));
6271 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6272 mDispatcher->waitForIdle();
6273 mFakePolicy->assertNotifyAnrWasNotCalled();
6274
6275 // Once a focused event arrives, we get an ANR for this application
6276 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6277 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006278 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006279 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6280 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006281 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006282 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006283 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006284 ASSERT_TRUE(mDispatcher->waitForIdle());
6285}
6286
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006287/**
6288 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6289 * there will not be an ANR.
6290 */
6291TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6292 mWindow->setFocusable(false);
6293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6294 mWindow->consumeFocusEvent(false);
6295
6296 KeyEvent event;
6297 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6298 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6299
6300 // Define a valid key down event that is stale (too old).
6301 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6302 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006303 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006304
6305 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6306
6307 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006308 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006309 InputEventInjectionSync::WAIT_FOR_RESULT,
6310 INJECT_EVENT_TIMEOUT, policyFlags);
6311 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6312 << "Injection should fail because the event is stale";
6313
6314 ASSERT_TRUE(mDispatcher->waitForIdle());
6315 mFakePolicy->assertNotifyAnrWasNotCalled();
6316 mWindow->assertNoEvents();
6317}
6318
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006319// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006320// Make sure that we don't notify policy twice about the same ANR.
6321TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006322 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006323 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6324 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006325
6326 // Once a focused event arrives, we get an ANR for this application
6327 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6328 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006329 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006330 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6331 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006332 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006333 const std::chrono::duration appTimeout =
6334 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6335 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006336
Vishnu Naire4df8752022-09-08 09:17:55 -07006337 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006338 // ANR should not be raised again. It is up to policy to do that if it desires.
6339 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006340
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006341 // If we now get a focused window, the ANR should stop, but the policy handles that via
6342 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006343 ASSERT_TRUE(mDispatcher->waitForIdle());
6344}
6345
6346// We have a focused application, but no focused window
6347TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006348 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6350 mWindow->consumeFocusEvent(false);
6351
6352 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006353 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006354 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006355 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6356 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006357
Vishnu Naire4df8752022-09-08 09:17:55 -07006358 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6359 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006360
6361 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006362 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006363 ASSERT_TRUE(mDispatcher->waitForIdle());
6364 mWindow->assertNoEvents();
6365}
6366
6367/**
6368 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6369 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6370 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6371 * the ANR mechanism should still work.
6372 *
6373 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6374 * DOWN event, while not responding on the second one.
6375 */
6376TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6377 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6378 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6379 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6380 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6381 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006382 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006383
6384 // Now send ACTION_UP, with identical timestamp
6385 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6386 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6387 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6388 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006389 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006390
6391 // We have now sent down and up. Let's consume first event and then ANR on the second.
6392 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6393 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006394 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006395}
6396
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006397// A spy window can receive an ANR
6398TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6399 sp<FakeWindowHandle> spy = addSpyWindow();
6400
6401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6402 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6403 WINDOW_LOCATION));
6404 mWindow->consumeMotionDown();
6405
6406 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6407 ASSERT_TRUE(sequenceNum);
6408 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006409 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006410
6411 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006412 spy->consumeMotionEvent(
6413 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006414 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006415 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006416}
6417
6418// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006419// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006420TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6421 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006422
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6424 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006425 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006427
6428 // Stuck on the ACTION_UP
6429 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006430 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006431
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006432 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006433 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006434 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6435 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006436
6437 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6438 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006439 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006440 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006441 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006442}
6443
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006444// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006445// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006446TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6447 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006448
6449 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006450 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6451 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006452
6453 mWindow->consumeMotionDown();
6454 // Stuck on the ACTION_UP
6455 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006456 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006457
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006458 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006459 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006460 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6461 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006462
6463 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6464 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006465 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006466 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006467 spy->assertNoEvents();
6468}
6469
6470TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6471 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6472
6473 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6474
6475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6476 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6477 WINDOW_LOCATION));
6478
6479 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6480 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6481 ASSERT_TRUE(consumeSeq);
6482
Prabir Pradhanedd96402022-02-15 01:46:16 -08006483 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006484
6485 monitor.finishEvent(*consumeSeq);
6486 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6487
6488 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006489 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006490}
6491
6492// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6493// process events, you don't get an anr. When the window later becomes unresponsive again, you
6494// get an ANR again.
6495// 1. tap -> block on ACTION_UP -> receive ANR
6496// 2. consume all pending events (= queue becomes healthy again)
6497// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6498TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6499 tapOnWindow();
6500
6501 mWindow->consumeMotionDown();
6502 // Block on ACTION_UP
6503 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006504 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006505 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6506 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006507 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006508 mWindow->assertNoEvents();
6509
6510 tapOnWindow();
6511 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006512 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006513 mWindow->consumeMotionUp();
6514
6515 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006516 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006517 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006518 mWindow->assertNoEvents();
6519}
6520
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006521// If a connection remains unresponsive for a while, make sure policy is only notified once about
6522// it.
6523TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006525 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6526 WINDOW_LOCATION));
6527
6528 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006529 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006530 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006531 // 'notifyConnectionUnresponsive' should only be called once per connection
6532 mFakePolicy->assertNotifyAnrWasNotCalled();
6533 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006534 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006535 mWindow->consumeMotionEvent(
6536 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006537 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006538 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006539 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006540 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006541}
6542
6543/**
6544 * If a window is processing a motion event, and then a key event comes in, the key event should
6545 * not to to the focused window until the motion is processed.
6546 *
6547 * Warning!!!
6548 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6549 * and the injection timeout that we specify when injecting the key.
6550 * We must have the injection timeout (10ms) be smaller than
6551 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6552 *
6553 * If that value changes, this test should also change.
6554 */
6555TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6556 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6558
6559 tapOnWindow();
6560 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6561 ASSERT_TRUE(downSequenceNum);
6562 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6563 ASSERT_TRUE(upSequenceNum);
6564 // Don't finish the events yet, and send a key
6565 // Injection will "succeed" because we will eventually give up and send the key to the focused
6566 // window even if motions are still being processed. But because the injection timeout is short,
6567 // we will receive INJECTION_TIMED_OUT as the result.
6568
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006569 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006570 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006571 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6572 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006573 // Key will not be sent to the window, yet, because the window is still processing events
6574 // and the key remains pending, waiting for the touch events to be processed
6575 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6576 ASSERT_FALSE(keySequenceNum);
6577
6578 std::this_thread::sleep_for(500ms);
6579 // if we wait long enough though, dispatcher will give up, and still send the key
6580 // to the focused window, even though we have not yet finished the motion event
6581 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6582 mWindow->finishEvent(*downSequenceNum);
6583 mWindow->finishEvent(*upSequenceNum);
6584}
6585
6586/**
6587 * If a window is processing a motion event, and then a key event comes in, the key event should
6588 * not go to the focused window until the motion is processed.
6589 * If then a new motion comes in, then the pending key event should be going to the currently
6590 * focused window right away.
6591 */
6592TEST_F(InputDispatcherSingleWindowAnr,
6593 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6594 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6595 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6596
6597 tapOnWindow();
6598 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6599 ASSERT_TRUE(downSequenceNum);
6600 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6601 ASSERT_TRUE(upSequenceNum);
6602 // Don't finish the events yet, and send a key
6603 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006605 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6606 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006607 // At this point, key is still pending, and should not be sent to the application yet.
6608 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6609 ASSERT_FALSE(keySequenceNum);
6610
6611 // Now tap down again. It should cause the pending key to go to the focused window right away.
6612 tapOnWindow();
6613 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6614 // the other events yet. We can finish events in any order.
6615 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6616 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6617 mWindow->consumeMotionDown();
6618 mWindow->consumeMotionUp();
6619 mWindow->assertNoEvents();
6620}
6621
6622class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6623 virtual void SetUp() override {
6624 InputDispatcherTest::SetUp();
6625
Chris Yea209fde2020-07-22 13:54:51 -07006626 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006627 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006628 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6629 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006630 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006631 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006632 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006633
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006634 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6635 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006636 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006637 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006638
6639 // Set focused application.
6640 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006641 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006642
6643 // Expect one focus window exist in display.
6644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006645 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006646 mFocusedWindow->consumeFocusEvent(true);
6647 }
6648
6649 virtual void TearDown() override {
6650 InputDispatcherTest::TearDown();
6651
6652 mUnfocusedWindow.clear();
6653 mFocusedWindow.clear();
6654 }
6655
6656protected:
Chris Yea209fde2020-07-22 13:54:51 -07006657 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006658 sp<FakeWindowHandle> mUnfocusedWindow;
6659 sp<FakeWindowHandle> mFocusedWindow;
6660 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6661 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6662 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6663
6664 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6665
6666 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6667
6668private:
6669 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006671 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6672 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006674 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6675 location));
6676 }
6677};
6678
6679// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6680// should be ANR'd first.
6681TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006683 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6684 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006686 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006687 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006688 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006689 // We consumed all events, so no ANR
6690 ASSERT_TRUE(mDispatcher->waitForIdle());
6691 mFakePolicy->assertNotifyAnrWasNotCalled();
6692
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006694 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6695 FOCUSED_WINDOW_LOCATION));
6696 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6697 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006698
6699 const std::chrono::duration timeout =
6700 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006701 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006702 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6703 // sequence to make it consistent
6704 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006705 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006706 mFocusedWindow->consumeMotionDown();
6707 // This cancel is generated because the connection was unresponsive
6708 mFocusedWindow->consumeMotionCancel();
6709 mFocusedWindow->assertNoEvents();
6710 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006711 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006712 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6713 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006714 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006715}
6716
6717// If we have 2 windows with identical timeouts that are both unresponsive,
6718// it doesn't matter which order they should have ANR.
6719// But we should receive ANR for both.
6720TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6721 // Set the timeout for unfocused window to match the focused window
6722 mUnfocusedWindow->setDispatchingTimeout(10ms);
6723 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6724
6725 tapOnFocusedWindow();
6726 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006727 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6728 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6729 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730
6731 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006732 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6733 mFocusedWindow->getToken() == anrConnectionToken2);
6734 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6735 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006736
6737 ASSERT_TRUE(mDispatcher->waitForIdle());
6738 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006739
6740 mFocusedWindow->consumeMotionDown();
6741 mFocusedWindow->consumeMotionUp();
6742 mUnfocusedWindow->consumeMotionOutside();
6743
Prabir Pradhanedd96402022-02-15 01:46:16 -08006744 sp<IBinder> responsiveToken1, responsiveToken2;
6745 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6746 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006747
6748 // Both applications should be marked as responsive, in any order
6749 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6750 mFocusedWindow->getToken() == responsiveToken2);
6751 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6752 mUnfocusedWindow->getToken() == responsiveToken2);
6753 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006754}
6755
6756// If a window is already not responding, the second tap on the same window should be ignored.
6757// We should also log an error to account for the dropped event (not tested here).
6758// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6759TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6760 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006761 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006762 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006763 // Receive the events, but don't respond
6764 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6765 ASSERT_TRUE(downEventSequenceNum);
6766 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6767 ASSERT_TRUE(upEventSequenceNum);
6768 const std::chrono::duration timeout =
6769 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006770 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006771
6772 // Tap once again
6773 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006775 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6776 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006777 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006778 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6779 FOCUSED_WINDOW_LOCATION));
6780 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6781 // valid touch target
6782 mUnfocusedWindow->assertNoEvents();
6783
6784 // Consume the first tap
6785 mFocusedWindow->finishEvent(*downEventSequenceNum);
6786 mFocusedWindow->finishEvent(*upEventSequenceNum);
6787 ASSERT_TRUE(mDispatcher->waitForIdle());
6788 // The second tap did not go to the focused window
6789 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006790 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006791 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6792 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793 mFakePolicy->assertNotifyAnrWasNotCalled();
6794}
6795
6796// If you tap outside of all windows, there will not be ANR
6797TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006798 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6800 LOCATION_OUTSIDE_ALL_WINDOWS));
6801 ASSERT_TRUE(mDispatcher->waitForIdle());
6802 mFakePolicy->assertNotifyAnrWasNotCalled();
6803}
6804
6805// Since the focused window is paused, tapping on it should not produce any events
6806TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6807 mFocusedWindow->setPaused(true);
6808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6809
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006811 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6812 FOCUSED_WINDOW_LOCATION));
6813
6814 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6815 ASSERT_TRUE(mDispatcher->waitForIdle());
6816 // Should not ANR because the window is paused, and touches shouldn't go to it
6817 mFakePolicy->assertNotifyAnrWasNotCalled();
6818
6819 mFocusedWindow->assertNoEvents();
6820 mUnfocusedWindow->assertNoEvents();
6821}
6822
6823/**
6824 * If a window is processing a motion event, and then a key event comes in, the key event should
6825 * not to to the focused window until the motion is processed.
6826 * If a different window becomes focused at this time, the key should go to that window instead.
6827 *
6828 * Warning!!!
6829 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6830 * and the injection timeout that we specify when injecting the key.
6831 * We must have the injection timeout (10ms) be smaller than
6832 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6833 *
6834 * If that value changes, this test should also change.
6835 */
6836TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
6837 // Set a long ANR timeout to prevent it from triggering
6838 mFocusedWindow->setDispatchingTimeout(2s);
6839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6840
6841 tapOnUnfocusedWindow();
6842 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
6843 ASSERT_TRUE(downSequenceNum);
6844 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
6845 ASSERT_TRUE(upSequenceNum);
6846 // Don't finish the events yet, and send a key
6847 // Injection will succeed because we will eventually give up and send the key to the focused
6848 // window even if motions are still being processed.
6849
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006850 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006851 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6852 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006854 // Key will not be sent to the window, yet, because the window is still processing events
6855 // and the key remains pending, waiting for the touch events to be processed
6856 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
6857 ASSERT_FALSE(keySequenceNum);
6858
6859 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07006860 mFocusedWindow->setFocusable(false);
6861 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006862 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006863 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006864
6865 // Focus events should precede the key events
6866 mUnfocusedWindow->consumeFocusEvent(true);
6867 mFocusedWindow->consumeFocusEvent(false);
6868
6869 // Finish the tap events, which should unblock dispatcher
6870 mUnfocusedWindow->finishEvent(*downSequenceNum);
6871 mUnfocusedWindow->finishEvent(*upSequenceNum);
6872
6873 // Now that all queues are cleared and no backlog in the connections, the key event
6874 // can finally go to the newly focused "mUnfocusedWindow".
6875 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6876 mFocusedWindow->assertNoEvents();
6877 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006878 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006879}
6880
6881// When the touch stream is split across 2 windows, and one of them does not respond,
6882// then ANR should be raised and the touch should be canceled for the unresponsive window.
6883// The other window should not be affected by that.
6884TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
6885 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00006886 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6887 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6888 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006889 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006890 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891
6892 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00006893 mDispatcher->notifyMotion(
6894 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6895 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006896
6897 const std::chrono::duration timeout =
6898 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006899 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006900
6901 mUnfocusedWindow->consumeMotionDown();
6902 mFocusedWindow->consumeMotionDown();
6903 // Focused window may or may not receive ACTION_MOVE
6904 // But it should definitely receive ACTION_CANCEL due to the ANR
6905 InputEvent* event;
6906 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
6907 ASSERT_TRUE(moveOrCancelSequenceNum);
6908 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
6909 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006910 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
6912 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
6913 mFocusedWindow->consumeMotionCancel();
6914 } else {
6915 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
6916 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006917 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006918 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6919 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006920
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921 mUnfocusedWindow->assertNoEvents();
6922 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006923 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006924}
6925
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006926/**
6927 * If we have no focused window, and a key comes in, we start the ANR timer.
6928 * The focused application should add a focused window before the timer runs out to prevent ANR.
6929 *
6930 * If the user touches another application during this time, the key should be dropped.
6931 * Next, if a new focused window comes in, without toggling the focused application,
6932 * then no ANR should occur.
6933 *
6934 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
6935 * but in some cases the policy may not update the focused application.
6936 */
6937TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
6938 std::shared_ptr<FakeApplicationHandle> focusedApplication =
6939 std::make_shared<FakeApplicationHandle>();
6940 focusedApplication->setDispatchingTimeout(60ms);
6941 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
6942 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
6943 mFocusedWindow->setFocusable(false);
6944
6945 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6946 mFocusedWindow->consumeFocusEvent(false);
6947
6948 // Send a key. The ANR timer should start because there is no focused window.
6949 // 'focusedApplication' will get blamed if this timer completes.
6950 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006951 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006952 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6953 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6954 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006956
6957 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
6958 // then the injected touches won't cause the focused event to get dropped.
6959 // The dispatcher only checks for whether the queue should be pruned upon queueing.
6960 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
6961 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
6962 // For this test, it means that the key would get delivered to the window once it becomes
6963 // focused.
6964 std::this_thread::sleep_for(10ms);
6965
6966 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006967 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6968 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6969 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006970
6971 // We do not consume the motion right away, because that would require dispatcher to first
6972 // process (== drop) the key event, and by that time, ANR will be raised.
6973 // Set the focused window first.
6974 mFocusedWindow->setFocusable(true);
6975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6976 setFocusedWindow(mFocusedWindow);
6977 mFocusedWindow->consumeFocusEvent(true);
6978 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
6979 // to another application. This could be a bug / behaviour in the policy.
6980
6981 mUnfocusedWindow->consumeMotionDown();
6982
6983 ASSERT_TRUE(mDispatcher->waitForIdle());
6984 // Should not ANR because we actually have a focused window. It was just added too slowly.
6985 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
6986}
6987
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05006988// These tests ensure we cannot send touch events to a window that's positioned behind a window
6989// that has feature NO_INPUT_CHANNEL.
6990// Layout:
6991// Top (closest to user)
6992// mNoInputWindow (above all windows)
6993// mBottomWindow
6994// Bottom (furthest from user)
6995class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
6996 virtual void SetUp() override {
6997 InputDispatcherTest::SetUp();
6998
6999 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007000 mNoInputWindow =
7001 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7002 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007003 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007004 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007005 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7006 // It's perfectly valid for this window to not have an associated input channel
7007
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007008 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7009 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007010 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7011
7012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7013 }
7014
7015protected:
7016 std::shared_ptr<FakeApplicationHandle> mApplication;
7017 sp<FakeWindowHandle> mNoInputWindow;
7018 sp<FakeWindowHandle> mBottomWindow;
7019};
7020
7021TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7022 PointF touchedPoint = {10, 10};
7023
Prabir Pradhan678438e2023-04-13 19:32:51 +00007024 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7025 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7026 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007027
7028 mNoInputWindow->assertNoEvents();
7029 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7030 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7031 // and therefore should prevent mBottomWindow from receiving touches
7032 mBottomWindow->assertNoEvents();
7033}
7034
7035/**
7036 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7037 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7038 */
7039TEST_F(InputDispatcherMultiWindowOcclusionTests,
7040 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007041 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7042 "Window with input channel and NO_INPUT_CHANNEL",
7043 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007044
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007045 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007046 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7048
7049 PointF touchedPoint = {10, 10};
7050
Prabir Pradhan678438e2023-04-13 19:32:51 +00007051 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7052 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7053 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007054
7055 mNoInputWindow->assertNoEvents();
7056 mBottomWindow->assertNoEvents();
7057}
7058
Vishnu Nair958da932020-08-21 17:12:37 -07007059class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7060protected:
7061 std::shared_ptr<FakeApplicationHandle> mApp;
7062 sp<FakeWindowHandle> mWindow;
7063 sp<FakeWindowHandle> mMirror;
7064
7065 virtual void SetUp() override {
7066 InputDispatcherTest::SetUp();
7067 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007068 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7069 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7070 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007071 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7072 mWindow->setFocusable(true);
7073 mMirror->setFocusable(true);
7074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7075 }
7076};
7077
7078TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7079 // Request focus on a mirrored window
7080 setFocusedWindow(mMirror);
7081
7082 // window gets focused
7083 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7085 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007086 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7087}
7088
7089// A focused & mirrored window remains focused only if the window and its mirror are both
7090// focusable.
7091TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7092 setFocusedWindow(mMirror);
7093
7094 // window gets focused
7095 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7097 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007098 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7100 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007101 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7102
7103 mMirror->setFocusable(false);
7104 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7105
7106 // window loses focus since one of the windows associated with the token in not focusable
7107 mWindow->consumeFocusEvent(false);
7108
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007109 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7110 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007111 mWindow->assertNoEvents();
7112}
7113
7114// A focused & mirrored window remains focused until the window and its mirror both become
7115// invisible.
7116TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7117 setFocusedWindow(mMirror);
7118
7119 // window gets focused
7120 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7122 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007123 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7125 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007126 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7127
7128 mMirror->setVisible(false);
7129 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7130
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7132 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007133 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7135 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007136 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7137
7138 mWindow->setVisible(false);
7139 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7140
7141 // window loses focus only after all windows associated with the token become invisible.
7142 mWindow->consumeFocusEvent(false);
7143
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007144 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7145 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007146 mWindow->assertNoEvents();
7147}
7148
7149// A focused & mirrored window remains focused until both windows are removed.
7150TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7151 setFocusedWindow(mMirror);
7152
7153 // window gets focused
7154 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7156 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007157 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7159 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007160 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7161
7162 // single window is removed but the window token remains focused
7163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7164
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7166 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007167 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7169 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007170 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7171
7172 // Both windows are removed
7173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7174 mWindow->consumeFocusEvent(false);
7175
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007176 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7177 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007178 mWindow->assertNoEvents();
7179}
7180
7181// Focus request can be pending until one window becomes visible.
7182TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7183 // Request focus on an invisible mirror.
7184 mWindow->setVisible(false);
7185 mMirror->setVisible(false);
7186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7187 setFocusedWindow(mMirror);
7188
7189 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007191 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7192 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007193
7194 mMirror->setVisible(true);
7195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7196
7197 // window gets focused
7198 mWindow->consumeFocusEvent(true);
7199 // window gets the pending key event
7200 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7201}
Prabir Pradhan99987712020-11-10 18:43:05 -08007202
7203class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7204protected:
7205 std::shared_ptr<FakeApplicationHandle> mApp;
7206 sp<FakeWindowHandle> mWindow;
7207 sp<FakeWindowHandle> mSecondWindow;
7208
7209 void SetUp() override {
7210 InputDispatcherTest::SetUp();
7211 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007212 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007213 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007214 mSecondWindow =
7215 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007216 mSecondWindow->setFocusable(true);
7217
7218 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7219 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7220
7221 setFocusedWindow(mWindow);
7222 mWindow->consumeFocusEvent(true);
7223 }
7224
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007225 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007226 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007227 }
7228
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007229 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7230 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007231 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007232 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7233 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007234 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007235 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007236 }
7237};
7238
7239TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7240 // Ensure that capture cannot be obtained for unfocused windows.
7241 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7242 mFakePolicy->assertSetPointerCaptureNotCalled();
7243 mSecondWindow->assertNoEvents();
7244
7245 // Ensure that capture can be enabled from the focus window.
7246 requestAndVerifyPointerCapture(mWindow, true);
7247
7248 // Ensure that capture cannot be disabled from a window that does not have capture.
7249 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7250 mFakePolicy->assertSetPointerCaptureNotCalled();
7251
7252 // Ensure that capture can be disabled from the window with capture.
7253 requestAndVerifyPointerCapture(mWindow, false);
7254}
7255
7256TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007257 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007258
7259 setFocusedWindow(mSecondWindow);
7260
7261 // Ensure that the capture disabled event was sent first.
7262 mWindow->consumeCaptureEvent(false);
7263 mWindow->consumeFocusEvent(false);
7264 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007265 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007266
7267 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007268 notifyPointerCaptureChanged({});
7269 notifyPointerCaptureChanged(request);
7270 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007271 mWindow->assertNoEvents();
7272 mSecondWindow->assertNoEvents();
7273 mFakePolicy->assertSetPointerCaptureNotCalled();
7274}
7275
7276TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007277 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007278
7279 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007280 notifyPointerCaptureChanged({});
7281 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007282
7283 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007284 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007285 mWindow->consumeCaptureEvent(false);
7286 mWindow->assertNoEvents();
7287}
7288
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007289TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7290 requestAndVerifyPointerCapture(mWindow, true);
7291
7292 // The first window loses focus.
7293 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007294 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007295 mWindow->consumeCaptureEvent(false);
7296
7297 // Request Pointer Capture from the second window before the notification from InputReader
7298 // arrives.
7299 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007300 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007301
7302 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007303 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007304
7305 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007306 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007307
7308 mSecondWindow->consumeFocusEvent(true);
7309 mSecondWindow->consumeCaptureEvent(true);
7310}
7311
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007312TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7313 // App repeatedly enables and disables capture.
7314 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7315 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7316 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7317 mFakePolicy->assertSetPointerCaptureCalled(false);
7318 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7319 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7320
7321 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7322 // first request is now stale, this should do nothing.
7323 notifyPointerCaptureChanged(firstRequest);
7324 mWindow->assertNoEvents();
7325
7326 // InputReader notifies that the second request was enabled.
7327 notifyPointerCaptureChanged(secondRequest);
7328 mWindow->consumeCaptureEvent(true);
7329}
7330
Prabir Pradhan7092e262022-05-03 16:51:09 +00007331TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7332 requestAndVerifyPointerCapture(mWindow, true);
7333
7334 // App toggles pointer capture off and on.
7335 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7336 mFakePolicy->assertSetPointerCaptureCalled(false);
7337
7338 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7339 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7340
7341 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7342 // preceding "disable" request.
7343 notifyPointerCaptureChanged(enableRequest);
7344
7345 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7346 // any notifications.
7347 mWindow->assertNoEvents();
7348}
7349
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007350class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7351protected:
7352 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007353
7354 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7355 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7356
7357 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7358 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7359
7360 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7361 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7362 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7363 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7364 MAXIMUM_OBSCURING_OPACITY);
7365
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007366 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007367 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007368 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007369
7370 sp<FakeWindowHandle> mTouchWindow;
7371
7372 virtual void SetUp() override {
7373 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007374 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007375 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7376 }
7377
7378 virtual void TearDown() override {
7379 InputDispatcherTest::TearDown();
7380 mTouchWindow.clear();
7381 }
7382
chaviw3277faf2021-05-19 16:45:23 -05007383 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7384 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007385 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007386 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007387 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007388 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007389 return window;
7390 }
7391
7392 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7393 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7394 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007395 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007396 // Generate an arbitrary PID based on the UID
7397 window->setOwnerInfo(1777 + (uid % 10000), uid);
7398 return window;
7399 }
7400
7401 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007402 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7403 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7404 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007405 }
7406};
7407
7408TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007409 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007410 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007412
7413 touch();
7414
7415 mTouchWindow->assertNoEvents();
7416}
7417
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007418TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007419 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7420 const sp<FakeWindowHandle>& w =
7421 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7422 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7423
7424 touch();
7425
7426 mTouchWindow->assertNoEvents();
7427}
7428
7429TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007430 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7431 const sp<FakeWindowHandle>& w =
7432 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7433 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7434
7435 touch();
7436
7437 w->assertNoEvents();
7438}
7439
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007440TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007441 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007443
7444 touch();
7445
7446 mTouchWindow->consumeAnyMotionDown();
7447}
7448
7449TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007450 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007451 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007452 w->setFrame(Rect(0, 0, 50, 50));
7453 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007454
7455 touch({PointF{100, 100}});
7456
7457 mTouchWindow->consumeAnyMotionDown();
7458}
7459
7460TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007461 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007462 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7464
7465 touch();
7466
7467 mTouchWindow->consumeAnyMotionDown();
7468}
7469
7470TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7471 const sp<FakeWindowHandle>& w =
7472 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007474
7475 touch();
7476
7477 mTouchWindow->consumeAnyMotionDown();
7478}
7479
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007480TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7481 const sp<FakeWindowHandle>& w =
7482 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7484
7485 touch();
7486
7487 w->assertNoEvents();
7488}
7489
7490/**
7491 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7492 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7493 * window, the occluding window will still receive ACTION_OUTSIDE event.
7494 */
7495TEST_F(InputDispatcherUntrustedTouchesTest,
7496 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7497 const sp<FakeWindowHandle>& w =
7498 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007499 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7501
7502 touch();
7503
7504 w->consumeMotionOutside();
7505}
7506
7507TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7508 const sp<FakeWindowHandle>& w =
7509 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007510 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7512
7513 touch();
7514
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007515 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007516}
7517
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007518TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007519 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007520 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7521 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7523
7524 touch();
7525
7526 mTouchWindow->consumeAnyMotionDown();
7527}
7528
7529TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7530 const sp<FakeWindowHandle>& w =
7531 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7532 MAXIMUM_OBSCURING_OPACITY);
7533 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007534
7535 touch();
7536
7537 mTouchWindow->consumeAnyMotionDown();
7538}
7539
7540TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007541 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007542 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7543 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007544 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7545
7546 touch();
7547
7548 mTouchWindow->assertNoEvents();
7549}
7550
7551TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7552 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7553 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007554 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7555 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007556 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007557 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7558 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007559 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7560
7561 touch();
7562
7563 mTouchWindow->assertNoEvents();
7564}
7565
7566TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7567 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7568 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007569 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7570 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007571 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007572 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7573 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7575
7576 touch();
7577
7578 mTouchWindow->consumeAnyMotionDown();
7579}
7580
7581TEST_F(InputDispatcherUntrustedTouchesTest,
7582 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7583 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007584 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7585 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007586 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007587 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7588 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7590
7591 touch();
7592
7593 mTouchWindow->consumeAnyMotionDown();
7594}
7595
7596TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7597 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007598 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7599 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007600 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007601 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7602 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007604
7605 touch();
7606
7607 mTouchWindow->assertNoEvents();
7608}
7609
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007610TEST_F(InputDispatcherUntrustedTouchesTest,
7611 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7612 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007613 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7614 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007615 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007616 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7617 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007618 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7619
7620 touch();
7621
7622 mTouchWindow->assertNoEvents();
7623}
7624
7625TEST_F(InputDispatcherUntrustedTouchesTest,
7626 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7627 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007628 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7629 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007630 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007631 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7632 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7634
7635 touch();
7636
7637 mTouchWindow->consumeAnyMotionDown();
7638}
7639
7640TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7641 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007642 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7643 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7645
7646 touch();
7647
7648 mTouchWindow->consumeAnyMotionDown();
7649}
7650
7651TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7652 const sp<FakeWindowHandle>& w =
7653 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7655
7656 touch();
7657
7658 mTouchWindow->consumeAnyMotionDown();
7659}
7660
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007661TEST_F(InputDispatcherUntrustedTouchesTest,
7662 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7663 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7664 const sp<FakeWindowHandle>& w =
7665 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7666 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7667
7668 touch();
7669
7670 mTouchWindow->assertNoEvents();
7671}
7672
7673TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7674 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7675 const sp<FakeWindowHandle>& w =
7676 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7677 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7678
7679 touch();
7680
7681 mTouchWindow->consumeAnyMotionDown();
7682}
7683
7684TEST_F(InputDispatcherUntrustedTouchesTest,
7685 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7686 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7687 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007688 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7689 OPACITY_ABOVE_THRESHOLD);
7690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7691
7692 touch();
7693
7694 mTouchWindow->consumeAnyMotionDown();
7695}
7696
7697TEST_F(InputDispatcherUntrustedTouchesTest,
7698 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7699 const sp<FakeWindowHandle>& w1 =
7700 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7701 OPACITY_BELOW_THRESHOLD);
7702 const sp<FakeWindowHandle>& w2 =
7703 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7704 OPACITY_BELOW_THRESHOLD);
7705 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7706
7707 touch();
7708
7709 mTouchWindow->assertNoEvents();
7710}
7711
7712/**
7713 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7714 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7715 * (which alone would result in allowing touches) does not affect the blocking behavior.
7716 */
7717TEST_F(InputDispatcherUntrustedTouchesTest,
7718 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7719 const sp<FakeWindowHandle>& wB =
7720 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7721 OPACITY_BELOW_THRESHOLD);
7722 const sp<FakeWindowHandle>& wC =
7723 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7724 OPACITY_BELOW_THRESHOLD);
7725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7726
7727 touch();
7728
7729 mTouchWindow->assertNoEvents();
7730}
7731
7732/**
7733 * This test is testing that a window from a different UID but with same application token doesn't
7734 * block the touch. Apps can share the application token for close UI collaboration for example.
7735 */
7736TEST_F(InputDispatcherUntrustedTouchesTest,
7737 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7738 const sp<FakeWindowHandle>& w =
7739 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7740 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7742
7743 touch();
7744
7745 mTouchWindow->consumeAnyMotionDown();
7746}
7747
arthurhungb89ccb02020-12-30 16:19:01 +08007748class InputDispatcherDragTests : public InputDispatcherTest {
7749protected:
7750 std::shared_ptr<FakeApplicationHandle> mApp;
7751 sp<FakeWindowHandle> mWindow;
7752 sp<FakeWindowHandle> mSecondWindow;
7753 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007754 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007755 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7756 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007757
7758 void SetUp() override {
7759 InputDispatcherTest::SetUp();
7760 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007761 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007762 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007763
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007764 mSecondWindow =
7765 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007766 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007767
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007768 mSpyWindow =
7769 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007770 mSpyWindow->setSpy(true);
7771 mSpyWindow->setTrustedOverlay(true);
7772 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7773
arthurhungb89ccb02020-12-30 16:19:01 +08007774 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007775 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007776 }
7777
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007778 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7779 switch (fromSource) {
7780 case AINPUT_SOURCE_TOUCHSCREEN:
7781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7782 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7783 ADISPLAY_ID_DEFAULT, {50, 50}))
7784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7785 break;
7786 case AINPUT_SOURCE_STYLUS:
7787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7788 injectMotionEvent(
7789 mDispatcher,
7790 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7791 AINPUT_SOURCE_STYLUS)
7792 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007793 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007794 .x(50)
7795 .y(50))
7796 .build()));
7797 break;
7798 case AINPUT_SOURCE_MOUSE:
7799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7800 injectMotionEvent(
7801 mDispatcher,
7802 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7803 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7804 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007805 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007806 .x(50)
7807 .y(50))
7808 .build()));
7809 break;
7810 default:
7811 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7812 }
arthurhungb89ccb02020-12-30 16:19:01 +08007813
7814 // Window should receive motion event.
7815 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007816 // Spy window should also receive motion event
7817 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007818 }
7819
7820 // Start performing drag, we will create a drag window and transfer touch to it.
7821 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7822 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007823 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007824 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007825 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00007826 }
arthurhungb89ccb02020-12-30 16:19:01 +08007827
7828 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007829 mDragWindow =
7830 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007831 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08007832 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007833 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007834
7835 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00007836 bool transferred =
7837 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00007838 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00007839 if (transferred) {
7840 mWindow->consumeMotionCancel();
7841 mDragWindow->consumeMotionDown();
7842 }
7843 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08007844 }
7845};
7846
7847TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007848 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08007849
7850 // Move on window.
7851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7852 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7853 ADISPLAY_ID_DEFAULT, {50, 50}))
7854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7855 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7856 mWindow->consumeDragEvent(false, 50, 50);
7857 mSecondWindow->assertNoEvents();
7858
7859 // Move to another window.
7860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7861 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7862 ADISPLAY_ID_DEFAULT, {150, 50}))
7863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7864 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7865 mWindow->consumeDragEvent(true, 150, 50);
7866 mSecondWindow->consumeDragEvent(false, 50, 50);
7867
7868 // Move back to original window.
7869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7870 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7871 ADISPLAY_ID_DEFAULT, {50, 50}))
7872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7873 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7874 mWindow->consumeDragEvent(false, 50, 50);
7875 mSecondWindow->consumeDragEvent(true, -50, 50);
7876
7877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7878 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
7879 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7880 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7881 mWindow->assertNoEvents();
7882 mSecondWindow->assertNoEvents();
7883}
7884
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007885TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007886 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007887
7888 // No cancel event after drag start
7889 mSpyWindow->assertNoEvents();
7890
7891 const MotionEvent secondFingerDownEvent =
7892 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
7895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007896 .build();
7897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7898 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7899 InputEventInjectionSync::WAIT_FOR_RESULT))
7900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7901
7902 // Receives cancel for first pointer after next pointer down
7903 mSpyWindow->consumeMotionCancel();
7904 mSpyWindow->consumeMotionDown();
7905
7906 mSpyWindow->assertNoEvents();
7907}
7908
arthurhungf452d0b2021-01-06 00:19:52 +08007909TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007910 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08007911
7912 // Move on window.
7913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7914 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7915 ADISPLAY_ID_DEFAULT, {50, 50}))
7916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7917 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7918 mWindow->consumeDragEvent(false, 50, 50);
7919 mSecondWindow->assertNoEvents();
7920
7921 // Move to another window.
7922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7923 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7924 ADISPLAY_ID_DEFAULT, {150, 50}))
7925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7926 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7927 mWindow->consumeDragEvent(true, 150, 50);
7928 mSecondWindow->consumeDragEvent(false, 50, 50);
7929
7930 // drop to another window.
7931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7932 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7933 {150, 50}))
7934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7935 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7936 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7937 mWindow->assertNoEvents();
7938 mSecondWindow->assertNoEvents();
7939}
7940
arthurhung6d4bed92021-03-17 11:59:33 +08007941TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007942 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08007943
7944 // Move on window and keep button pressed.
7945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7946 injectMotionEvent(mDispatcher,
7947 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7948 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007949 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08007950 .build()))
7951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7952 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7953 mWindow->consumeDragEvent(false, 50, 50);
7954 mSecondWindow->assertNoEvents();
7955
7956 // Move to another window and release button, expect to drop item.
7957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7958 injectMotionEvent(mDispatcher,
7959 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7960 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007961 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08007962 .build()))
7963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7964 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7965 mWindow->assertNoEvents();
7966 mSecondWindow->assertNoEvents();
7967 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7968
7969 // nothing to the window.
7970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7971 injectMotionEvent(mDispatcher,
7972 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
7973 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007974 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08007975 .build()))
7976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7977 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7978 mWindow->assertNoEvents();
7979 mSecondWindow->assertNoEvents();
7980}
7981
Arthur Hung54745652022-04-20 07:17:41 +00007982TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007983 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08007984
7985 // Set second window invisible.
7986 mSecondWindow->setVisible(false);
7987 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
7988
7989 // Move on window.
7990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7991 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7992 ADISPLAY_ID_DEFAULT, {50, 50}))
7993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7994 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7995 mWindow->consumeDragEvent(false, 50, 50);
7996 mSecondWindow->assertNoEvents();
7997
7998 // Move to another window.
7999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8000 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8001 ADISPLAY_ID_DEFAULT, {150, 50}))
8002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8003 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8004 mWindow->consumeDragEvent(true, 150, 50);
8005 mSecondWindow->assertNoEvents();
8006
8007 // drop to another window.
8008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8009 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8010 {150, 50}))
8011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8012 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8013 mFakePolicy->assertDropTargetEquals(nullptr);
8014 mWindow->assertNoEvents();
8015 mSecondWindow->assertNoEvents();
8016}
8017
Arthur Hung54745652022-04-20 07:17:41 +00008018TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008019 // Ensure window could track pointerIds if it didn't support split touch.
8020 mWindow->setPreventSplitting(true);
8021
Arthur Hung54745652022-04-20 07:17:41 +00008022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8023 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8024 {50, 50}))
8025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8026 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8027
8028 const MotionEvent secondFingerDownEvent =
8029 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8030 .displayId(ADISPLAY_ID_DEFAULT)
8031 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008032 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8033 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008034 .build();
8035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8036 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8037 InputEventInjectionSync::WAIT_FOR_RESULT))
8038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008039 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008040
8041 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008042 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008043}
8044
8045TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8046 // First down on second window.
8047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8048 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8049 {150, 50}))
8050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8051
8052 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8053
8054 // Second down on first window.
8055 const MotionEvent secondFingerDownEvent =
8056 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8057 .displayId(ADISPLAY_ID_DEFAULT)
8058 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008059 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8060 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008061 .build();
8062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8063 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8064 InputEventInjectionSync::WAIT_FOR_RESULT))
8065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8066 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8067
8068 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008069 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008070
8071 // Move on window.
8072 const MotionEvent secondFingerMoveEvent =
8073 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8074 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008075 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8076 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008077 .build();
8078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8079 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8080 InputEventInjectionSync::WAIT_FOR_RESULT));
8081 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8082 mWindow->consumeDragEvent(false, 50, 50);
8083 mSecondWindow->consumeMotionMove();
8084
8085 // Release the drag pointer should perform drop.
8086 const MotionEvent secondFingerUpEvent =
8087 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8088 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008089 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8090 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008091 .build();
8092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8093 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8094 InputEventInjectionSync::WAIT_FOR_RESULT));
8095 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8096 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8097 mWindow->assertNoEvents();
8098 mSecondWindow->consumeMotionMove();
8099}
8100
Arthur Hung3915c1f2022-05-31 07:17:17 +00008101TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008102 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008103
8104 // Update window of second display.
8105 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008106 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008107 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8108
8109 // Let second display has a touch state.
8110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8111 injectMotionEvent(mDispatcher,
8112 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8113 AINPUT_SOURCE_TOUCHSCREEN)
8114 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008115 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008116 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008117 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008118 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008119 // Update window again.
8120 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8121
8122 // Move on window.
8123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8124 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8125 ADISPLAY_ID_DEFAULT, {50, 50}))
8126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8127 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8128 mWindow->consumeDragEvent(false, 50, 50);
8129 mSecondWindow->assertNoEvents();
8130
8131 // Move to another window.
8132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8133 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8134 ADISPLAY_ID_DEFAULT, {150, 50}))
8135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8136 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8137 mWindow->consumeDragEvent(true, 150, 50);
8138 mSecondWindow->consumeDragEvent(false, 50, 50);
8139
8140 // drop to another window.
8141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8142 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8143 {150, 50}))
8144 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8145 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8146 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8147 mWindow->assertNoEvents();
8148 mSecondWindow->assertNoEvents();
8149}
8150
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008151TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8152 startDrag(true, AINPUT_SOURCE_MOUSE);
8153 // Move on window.
8154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8155 injectMotionEvent(mDispatcher,
8156 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8157 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8158 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008159 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008160 .x(50)
8161 .y(50))
8162 .build()))
8163 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8164 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8165 mWindow->consumeDragEvent(false, 50, 50);
8166 mSecondWindow->assertNoEvents();
8167
8168 // Move to another window.
8169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8170 injectMotionEvent(mDispatcher,
8171 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8172 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8173 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008174 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008175 .x(150)
8176 .y(50))
8177 .build()))
8178 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8179 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8180 mWindow->consumeDragEvent(true, 150, 50);
8181 mSecondWindow->consumeDragEvent(false, 50, 50);
8182
8183 // drop to another window.
8184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8185 injectMotionEvent(mDispatcher,
8186 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8187 .buttonState(0)
8188 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008189 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008190 .x(150)
8191 .y(50))
8192 .build()))
8193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8194 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8195 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8196 mWindow->assertNoEvents();
8197 mSecondWindow->assertNoEvents();
8198}
8199
Vishnu Nair062a8672021-09-03 16:07:44 -07008200class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8201
8202TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008204 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8205 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008206 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8208 window->setFocusable(true);
8209 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8210 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008211 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008212
8213 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008214 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008215 window->assertNoEvents();
8216
Prabir Pradhan678438e2023-04-13 19:32:51 +00008217 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8218 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008219 window->assertNoEvents();
8220
8221 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008222 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8224
Prabir Pradhan678438e2023-04-13 19:32:51 +00008225 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008226 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8227
Prabir Pradhan678438e2023-04-13 19:32:51 +00008228 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8229 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008230 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8231 window->assertNoEvents();
8232}
8233
8234TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8235 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8236 std::make_shared<FakeApplicationHandle>();
8237 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008238 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8239 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008240 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8241 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008242 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008243 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008244 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8245 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008246 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008247 window->setOwnerInfo(222, 222);
8248 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8249 window->setFocusable(true);
8250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8251 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008252 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008253
8254 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008255 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008256 window->assertNoEvents();
8257
Prabir Pradhan678438e2023-04-13 19:32:51 +00008258 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8259 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008260 window->assertNoEvents();
8261
8262 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008263 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008264 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8265
Prabir Pradhan678438e2023-04-13 19:32:51 +00008266 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008267 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8268
Prabir Pradhan678438e2023-04-13 19:32:51 +00008269 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8270 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008271 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8272 window->assertNoEvents();
8273}
8274
8275TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8276 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8277 std::make_shared<FakeApplicationHandle>();
8278 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008279 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8280 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008281 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8282 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008283 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008285 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8286 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008287 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008288 window->setOwnerInfo(222, 222);
8289 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8290 window->setFocusable(true);
8291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8292 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008293 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008294
8295 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008296 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008297 window->assertNoEvents();
8298
Prabir Pradhan678438e2023-04-13 19:32:51 +00008299 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8300 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008301 window->assertNoEvents();
8302
8303 // When the window is no longer obscured because it went on top, it should get input
8304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8305
Prabir Pradhan678438e2023-04-13 19:32:51 +00008306 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008307 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8308
Prabir Pradhan678438e2023-04-13 19:32:51 +00008309 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8310 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008311 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8312 window->assertNoEvents();
8313}
8314
Antonio Kantekf16f2832021-09-28 04:39:20 +00008315class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8316protected:
8317 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008318 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008319 sp<FakeWindowHandle> mWindow;
8320 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008321 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008322
8323 void SetUp() override {
8324 InputDispatcherTest::SetUp();
8325
8326 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008327 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008328 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008329 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008330 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008331 mSecondWindow =
8332 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008333 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008334 mThirdWindow =
8335 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8336 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8337 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008338
8339 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8341 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8342 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008343 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008344
Antonio Kantek15beb512022-06-13 22:35:41 +00008345 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008346 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008347 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008348 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8349 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008350 mThirdWindow->assertNoEvents();
8351 }
8352
8353 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8354 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008355 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008356 SECOND_DISPLAY_ID)) {
8357 mWindow->assertNoEvents();
8358 mSecondWindow->assertNoEvents();
8359 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008360 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008361 }
8362
Antonio Kantek15beb512022-06-13 22:35:41 +00008363 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8364 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008365 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8366 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008367 mWindow->consumeTouchModeEvent(inTouchMode);
8368 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008369 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008370 }
8371};
8372
Antonio Kantek26defcf2022-02-08 01:12:27 +00008373TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008374 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008375 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8376 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008377 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008378}
8379
Antonio Kantek26defcf2022-02-08 01:12:27 +00008380TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8381 const WindowInfo& windowInfo = *mWindow->getInfo();
8382 int32_t ownerPid = windowInfo.ownerPid;
8383 int32_t ownerUid = windowInfo.ownerUid;
8384 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8385 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008386 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008387 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008388 mWindow->assertNoEvents();
8389 mSecondWindow->assertNoEvents();
8390}
8391
8392TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8393 const WindowInfo& windowInfo = *mWindow->getInfo();
8394 int32_t ownerPid = windowInfo.ownerPid;
8395 int32_t ownerUid = windowInfo.ownerUid;
8396 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008397 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008398 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008399}
8400
Antonio Kantekf16f2832021-09-28 04:39:20 +00008401TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008402 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008403 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8404 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008405 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008406 mWindow->assertNoEvents();
8407 mSecondWindow->assertNoEvents();
8408}
8409
Antonio Kantek15beb512022-06-13 22:35:41 +00008410TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8411 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8412 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8413 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008414 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008415 mWindow->assertNoEvents();
8416 mSecondWindow->assertNoEvents();
8417 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8418}
8419
Antonio Kantek48710e42022-03-24 14:19:30 -07008420TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8421 // Interact with the window first.
8422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8423 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8424 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8425
8426 // Then remove focus.
8427 mWindow->setFocusable(false);
8428 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8429
8430 // Assert that caller can switch touch mode by owning one of the last interacted window.
8431 const WindowInfo& windowInfo = *mWindow->getInfo();
8432 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8433 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008434 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008435}
8436
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008437class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8438public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008439 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008440 std::shared_ptr<FakeApplicationHandle> application =
8441 std::make_shared<FakeApplicationHandle>();
8442 std::string name = "Fake Spy ";
8443 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008444 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8445 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008446 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008447 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008448 return spy;
8449 }
8450
8451 sp<FakeWindowHandle> createForeground() {
8452 std::shared_ptr<FakeApplicationHandle> application =
8453 std::make_shared<FakeApplicationHandle>();
8454 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008455 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8456 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008457 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008458 return window;
8459 }
8460
8461private:
8462 int mSpyCount{0};
8463};
8464
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008465using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008466/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008467 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8468 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008469TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8470 ScopedSilentDeath _silentDeath;
8471
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008472 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008473 spy->setTrustedOverlay(false);
8474 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8475 ".* not a trusted overlay");
8476}
8477
8478/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008479 * Input injection into a display with a spy window but no foreground windows should succeed.
8480 */
8481TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008482 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8484
8485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8486 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8488 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8489}
8490
8491/**
8492 * Verify the order in which different input windows receive events. The touched foreground window
8493 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8494 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8495 * receive events before ones belows it.
8496 *
8497 * Here, we set up a scenario with four windows in the following Z order from the top:
8498 * spy1, spy2, window, spy3.
8499 * We then inject an event and verify that the foreground "window" receives it first, followed by
8500 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8501 * window.
8502 */
8503TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8504 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008505 auto spy1 = createSpy();
8506 auto spy2 = createSpy();
8507 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008508 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8509 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8510 const size_t numChannels = channels.size();
8511
Michael Wright8e9a8562022-02-09 13:44:29 +00008512 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008513 if (!epollFd.ok()) {
8514 FAIL() << "Failed to create epoll fd";
8515 }
8516
8517 for (size_t i = 0; i < numChannels; i++) {
8518 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8519 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8520 FAIL() << "Failed to add fd to epoll";
8521 }
8522 }
8523
8524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8525 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8527
8528 std::vector<size_t> eventOrder;
8529 std::vector<struct epoll_event> events(numChannels);
8530 for (;;) {
8531 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8532 (100ms).count());
8533 if (nFds < 0) {
8534 FAIL() << "Failed to call epoll_wait";
8535 }
8536 if (nFds == 0) {
8537 break; // epoll_wait timed out
8538 }
8539 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008540 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008541 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008542 channels[i]->consumeMotionDown();
8543 }
8544 }
8545
8546 // Verify the order in which the events were received.
8547 EXPECT_EQ(3u, eventOrder.size());
8548 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8549 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8550 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8551}
8552
8553/**
8554 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8555 */
8556TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8557 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008558 auto spy = createSpy();
8559 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008560 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8561
8562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8563 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8564 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8565 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8566 spy->assertNoEvents();
8567}
8568
8569/**
8570 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8571 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8572 * to the window.
8573 */
8574TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8575 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008576 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008577 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8578 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8579
8580 // Inject an event outside the spy window's touchable region.
8581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8582 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8584 window->consumeMotionDown();
8585 spy->assertNoEvents();
8586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8587 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8589 window->consumeMotionUp();
8590 spy->assertNoEvents();
8591
8592 // Inject an event inside the spy window's touchable region.
8593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8594 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8595 {5, 10}))
8596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8597 window->consumeMotionDown();
8598 spy->consumeMotionDown();
8599}
8600
8601/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008602 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008603 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008604 */
8605TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8606 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008607 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008608 auto spy = createSpy();
8609 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008610 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008611 spy->setFrame(Rect{0, 0, 20, 20});
8612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8613
8614 // Inject an event outside the spy window's frame and touchable region.
8615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008616 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8617 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8619 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008620 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008621}
8622
8623/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008624 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8625 * pointers that are down within its bounds.
8626 */
8627TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8628 auto windowLeft = createForeground();
8629 windowLeft->setFrame({0, 0, 100, 200});
8630 auto windowRight = createForeground();
8631 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008632 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008633 spy->setFrame({0, 0, 200, 200});
8634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8635
8636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8637 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8638 {50, 50}))
8639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8640 windowLeft->consumeMotionDown();
8641 spy->consumeMotionDown();
8642
8643 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008644 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008645 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008646 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8647 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008648 .build();
8649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8650 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8651 InputEventInjectionSync::WAIT_FOR_RESULT))
8652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8653 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008654 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008655}
8656
8657/**
8658 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8659 * the spy should receive the second pointer with ACTION_DOWN.
8660 */
8661TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8662 auto window = createForeground();
8663 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008664 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008665 spyRight->setFrame({100, 0, 200, 200});
8666 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8667
8668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8669 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8670 {50, 50}))
8671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8672 window->consumeMotionDown();
8673 spyRight->assertNoEvents();
8674
8675 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008676 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008677 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008678 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8679 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008680 .build();
8681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8682 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8683 InputEventInjectionSync::WAIT_FOR_RESULT))
8684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008685 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008686 spyRight->consumeMotionDown();
8687}
8688
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008689/**
8690 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8691 * windows should be allowed to control split touch.
8692 */
8693TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008694 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008695 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008696 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008697 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008698
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008699 auto window = createForeground();
8700 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008701
8702 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8703
8704 // First finger down, no window touched.
8705 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8706 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8707 {100, 200}))
8708 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8709 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8710 window->assertNoEvents();
8711
8712 // Second finger down on window, the window should receive touch down.
8713 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008714 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008715 .displayId(ADISPLAY_ID_DEFAULT)
8716 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008717 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8718 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008719 .build();
8720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8721 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8722 InputEventInjectionSync::WAIT_FOR_RESULT))
8723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8724
8725 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008726 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008727}
8728
8729/**
8730 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8731 * do not receive key events.
8732 */
8733TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008734 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008735 spy->setFocusable(false);
8736
8737 auto window = createForeground();
8738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8739 setFocusedWindow(window);
8740 window->consumeFocusEvent(true);
8741
8742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8743 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8744 window->consumeKeyDown(ADISPLAY_ID_NONE);
8745
8746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8747 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8748 window->consumeKeyUp(ADISPLAY_ID_NONE);
8749
8750 spy->assertNoEvents();
8751}
8752
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008753using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8754
8755/**
8756 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8757 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8758 */
8759TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8760 auto window = createForeground();
8761 auto spy1 = createSpy();
8762 auto spy2 = createSpy();
8763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8764
8765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8766 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8768 window->consumeMotionDown();
8769 spy1->consumeMotionDown();
8770 spy2->consumeMotionDown();
8771
8772 // Pilfer pointers from the second spy window.
8773 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8774 spy2->assertNoEvents();
8775 spy1->consumeMotionCancel();
8776 window->consumeMotionCancel();
8777
8778 // The rest of the gesture should only be sent to the second spy window.
8779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8780 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8781 ADISPLAY_ID_DEFAULT))
8782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8783 spy2->consumeMotionMove();
8784 spy1->assertNoEvents();
8785 window->assertNoEvents();
8786}
8787
8788/**
8789 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8790 * in the middle of the gesture.
8791 */
8792TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8793 auto window = createForeground();
8794 auto spy = createSpy();
8795 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8796
8797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8798 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8799 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8800 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8801 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8802
8803 window->releaseChannel();
8804
8805 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8806
8807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8808 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8810 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8811}
8812
8813/**
8814 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8815 * the spy, but not to any other windows.
8816 */
8817TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8818 auto spy = createSpy();
8819 auto window = createForeground();
8820
8821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8822
8823 // First finger down on the window and the spy.
8824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8825 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8826 {100, 200}))
8827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8828 spy->consumeMotionDown();
8829 window->consumeMotionDown();
8830
8831 // Spy window pilfers the pointers.
8832 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8833 window->consumeMotionCancel();
8834
8835 // Second finger down on the window and spy, but the window should not receive the pointer down.
8836 const MotionEvent secondFingerDownEvent =
8837 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8838 .displayId(ADISPLAY_ID_DEFAULT)
8839 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008840 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8841 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008842 .build();
8843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8844 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8845 InputEventInjectionSync::WAIT_FOR_RESULT))
8846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8847
Harry Cutts33476232023-01-30 19:57:29 +00008848 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008849
8850 // Third finger goes down outside all windows, so injection should fail.
8851 const MotionEvent thirdFingerDownEvent =
8852 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8853 .displayId(ADISPLAY_ID_DEFAULT)
8854 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008855 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8856 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
8857 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008858 .build();
8859 ASSERT_EQ(InputEventInjectionResult::FAILED,
8860 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8861 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008862 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008863
8864 spy->assertNoEvents();
8865 window->assertNoEvents();
8866}
8867
8868/**
8869 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
8870 */
8871TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
8872 auto spy = createSpy();
8873 spy->setFrame(Rect(0, 0, 100, 100));
8874 auto window = createForeground();
8875 window->setFrame(Rect(0, 0, 200, 200));
8876
8877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8878
8879 // First finger down on the window only
8880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8881 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8882 {150, 150}))
8883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8884 window->consumeMotionDown();
8885
8886 // Second finger down on the spy and window
8887 const MotionEvent secondFingerDownEvent =
8888 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8889 .displayId(ADISPLAY_ID_DEFAULT)
8890 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008891 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
8892 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008893 .build();
8894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8895 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8896 InputEventInjectionSync::WAIT_FOR_RESULT))
8897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8898 spy->consumeMotionDown();
8899 window->consumeMotionPointerDown(1);
8900
8901 // Third finger down on the spy and window
8902 const MotionEvent thirdFingerDownEvent =
8903 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8904 .displayId(ADISPLAY_ID_DEFAULT)
8905 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008906 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
8907 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
8908 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008909 .build();
8910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8911 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8912 InputEventInjectionSync::WAIT_FOR_RESULT))
8913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8914 spy->consumeMotionPointerDown(1);
8915 window->consumeMotionPointerDown(2);
8916
8917 // Spy window pilfers the pointers.
8918 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8919 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8920 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8921
8922 spy->assertNoEvents();
8923 window->assertNoEvents();
8924}
8925
8926/**
8927 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
8928 * other windows should be canceled. If this results in the cancellation of all pointers for some
8929 * window, then that window should receive ACTION_CANCEL.
8930 */
8931TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
8932 auto spy = createSpy();
8933 spy->setFrame(Rect(0, 0, 100, 100));
8934 auto window = createForeground();
8935 window->setFrame(Rect(0, 0, 200, 200));
8936
8937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8938
8939 // First finger down on both spy and window
8940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8941 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8942 {10, 10}))
8943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8944 window->consumeMotionDown();
8945 spy->consumeMotionDown();
8946
8947 // Second finger down on the spy and window
8948 const MotionEvent secondFingerDownEvent =
8949 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8950 .displayId(ADISPLAY_ID_DEFAULT)
8951 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008952 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
8953 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008954 .build();
8955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8956 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8957 InputEventInjectionSync::WAIT_FOR_RESULT))
8958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8959 spy->consumeMotionPointerDown(1);
8960 window->consumeMotionPointerDown(1);
8961
8962 // Spy window pilfers the pointers.
8963 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8964 window->consumeMotionCancel();
8965
8966 spy->assertNoEvents();
8967 window->assertNoEvents();
8968}
8969
8970/**
8971 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
8972 * be sent to other windows
8973 */
8974TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
8975 auto spy = createSpy();
8976 spy->setFrame(Rect(0, 0, 100, 100));
8977 auto window = createForeground();
8978 window->setFrame(Rect(0, 0, 200, 200));
8979
8980 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8981
8982 // First finger down on both window and spy
8983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8984 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8985 {10, 10}))
8986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8987 window->consumeMotionDown();
8988 spy->consumeMotionDown();
8989
8990 // Spy window pilfers the pointers.
8991 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8992 window->consumeMotionCancel();
8993
8994 // Second finger down on the window only
8995 const MotionEvent secondFingerDownEvent =
8996 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8997 .displayId(ADISPLAY_ID_DEFAULT)
8998 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008999 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9000 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009001 .build();
9002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9003 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9004 InputEventInjectionSync::WAIT_FOR_RESULT))
9005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9006 window->consumeMotionDown();
9007 window->assertNoEvents();
9008
9009 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9010 spy->consumeMotionMove();
9011 spy->assertNoEvents();
9012}
9013
Prabir Pradhand65552b2021-10-07 11:23:50 -07009014class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9015public:
9016 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9017 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9018 std::make_shared<FakeApplicationHandle>();
9019 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009020 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9021 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009022 overlay->setFocusable(false);
9023 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009024 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009025 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009026 overlay->setTrustedOverlay(true);
9027
9028 std::shared_ptr<FakeApplicationHandle> application =
9029 std::make_shared<FakeApplicationHandle>();
9030 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009031 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9032 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009033 window->setFocusable(true);
9034 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009035
9036 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9038 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009039 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009040 return {std::move(overlay), std::move(window)};
9041 }
9042
9043 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009044 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009045 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009046 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009047 }
9048
9049 void sendStylusEvent(int32_t action) {
9050 NotifyMotionArgs motionArgs =
9051 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9052 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009053 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009054 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009055 }
9056};
9057
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009058using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9059
9060TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9061 ScopedSilentDeath _silentDeath;
9062
Prabir Pradhand65552b2021-10-07 11:23:50 -07009063 auto [overlay, window] = setupStylusOverlayScenario();
9064 overlay->setTrustedOverlay(false);
9065 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9066 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9067 ".* not a trusted overlay");
9068}
9069
9070TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9071 auto [overlay, window] = setupStylusOverlayScenario();
9072 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9073
9074 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9075 overlay->consumeMotionDown();
9076 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9077 overlay->consumeMotionUp();
9078
9079 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9080 window->consumeMotionDown();
9081 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9082 window->consumeMotionUp();
9083
9084 overlay->assertNoEvents();
9085 window->assertNoEvents();
9086}
9087
9088TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9089 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009090 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9092
9093 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9094 overlay->consumeMotionDown();
9095 window->consumeMotionDown();
9096 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9097 overlay->consumeMotionUp();
9098 window->consumeMotionUp();
9099
9100 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9101 window->consumeMotionDown();
9102 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9103 window->consumeMotionUp();
9104
9105 overlay->assertNoEvents();
9106 window->assertNoEvents();
9107}
9108
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009109/**
9110 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9111 * The scenario is as follows:
9112 * - The stylus interceptor overlay is configured as a spy window.
9113 * - The stylus interceptor spy receives the start of a new stylus gesture.
9114 * - It pilfers pointers and then configures itself to no longer be a spy.
9115 * - The stylus interceptor continues to receive the rest of the gesture.
9116 */
9117TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9118 auto [overlay, window] = setupStylusOverlayScenario();
9119 overlay->setSpy(true);
9120 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9121
9122 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9123 overlay->consumeMotionDown();
9124 window->consumeMotionDown();
9125
9126 // The interceptor pilfers the pointers.
9127 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9128 window->consumeMotionCancel();
9129
9130 // The interceptor configures itself so that it is no longer a spy.
9131 overlay->setSpy(false);
9132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9133
9134 // It continues to receive the rest of the stylus gesture.
9135 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9136 overlay->consumeMotionMove();
9137 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9138 overlay->consumeMotionUp();
9139
9140 window->assertNoEvents();
9141}
9142
Prabir Pradhan5735a322022-04-11 17:23:34 +00009143struct User {
9144 int32_t mPid;
9145 int32_t mUid;
9146 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9147 std::unique_ptr<InputDispatcher>& mDispatcher;
9148
9149 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9150 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9151
9152 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9153 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9154 ADISPLAY_ID_DEFAULT, {100, 200},
9155 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9156 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9157 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9158 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9159 }
9160
9161 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009162 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009163 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009164 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009165 mPolicyFlags);
9166 }
9167
9168 sp<FakeWindowHandle> createWindow() const {
9169 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9170 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009171 sp<FakeWindowHandle> window =
9172 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9173 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009174 window->setOwnerInfo(mPid, mUid);
9175 return window;
9176 }
9177};
9178
9179using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9180
9181TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9182 auto owner = User(mDispatcher, 10, 11);
9183 auto window = owner.createWindow();
9184 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9185
9186 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9187 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9188 window->consumeMotionDown();
9189
9190 setFocusedWindow(window);
9191 window->consumeFocusEvent(true);
9192
9193 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9194 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9195 window->consumeKeyDown(ADISPLAY_ID_NONE);
9196}
9197
9198TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9199 auto owner = User(mDispatcher, 10, 11);
9200 auto window = owner.createWindow();
9201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9202
9203 auto rando = User(mDispatcher, 20, 21);
9204 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9205 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9206
9207 setFocusedWindow(window);
9208 window->consumeFocusEvent(true);
9209
9210 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9211 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9212 window->assertNoEvents();
9213}
9214
9215TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9216 auto owner = User(mDispatcher, 10, 11);
9217 auto window = owner.createWindow();
9218 auto spy = owner.createWindow();
9219 spy->setSpy(true);
9220 spy->setTrustedOverlay(true);
9221 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9222
9223 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9224 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9225 spy->consumeMotionDown();
9226 window->consumeMotionDown();
9227}
9228
9229TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9230 auto owner = User(mDispatcher, 10, 11);
9231 auto window = owner.createWindow();
9232
9233 auto rando = User(mDispatcher, 20, 21);
9234 auto randosSpy = rando.createWindow();
9235 randosSpy->setSpy(true);
9236 randosSpy->setTrustedOverlay(true);
9237 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9238
9239 // The event is targeted at owner's window, so injection should succeed, but the spy should
9240 // not receive the event.
9241 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9242 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9243 randosSpy->assertNoEvents();
9244 window->consumeMotionDown();
9245}
9246
9247TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9248 auto owner = User(mDispatcher, 10, 11);
9249 auto window = owner.createWindow();
9250
9251 auto rando = User(mDispatcher, 20, 21);
9252 auto randosSpy = rando.createWindow();
9253 randosSpy->setSpy(true);
9254 randosSpy->setTrustedOverlay(true);
9255 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9256
9257 // A user that has injection permission can inject into any window.
9258 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9259 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9260 ADISPLAY_ID_DEFAULT));
9261 randosSpy->consumeMotionDown();
9262 window->consumeMotionDown();
9263
9264 setFocusedWindow(randosSpy);
9265 randosSpy->consumeFocusEvent(true);
9266
9267 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9268 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9269 window->assertNoEvents();
9270}
9271
9272TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9273 auto owner = User(mDispatcher, 10, 11);
9274 auto window = owner.createWindow();
9275
9276 auto rando = User(mDispatcher, 20, 21);
9277 auto randosWindow = rando.createWindow();
9278 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9279 randosWindow->setWatchOutsideTouch(true);
9280 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9281
9282 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9283 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9284 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9285 window->consumeMotionDown();
9286 randosWindow->consumeMotionOutside();
9287}
9288
Garfield Tane84e6f92019-08-29 17:28:41 -07009289} // namespace android::inputdispatcher