blob: 147b7d4a833b9dfef33cc074ad9726f6cfa5f0de [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
Josep del Riob3981622023-04-18 15:49:45 +0000405 void assertUserActivityPoked() {
406 std::scoped_lock lock(mLock);
407 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
408 }
409
410 void assertUserActivityNotPoked() {
411 std::scoped_lock lock(mLock);
412 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
413 }
414
Michael Wrightd02c5b62014-02-10 15:10:22 -0800415private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700416 std::mutex mLock;
417 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
418 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
419 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
420 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800421
Prabir Pradhan99987712020-11-10 18:43:05 -0800422 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000423
424 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800425
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700426 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700427 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800428 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
429 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700430 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800431 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
432 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700433
arthurhungf452d0b2021-01-06 00:19:52 +0800434 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800435 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000436 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800437
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800438 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
439
Prabir Pradhanedd96402022-02-15 01:46:16 -0800440 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
441 // for a specific container to become non-empty. When the container is non-empty, return the
442 // first entry from the container and erase it.
443 template <class T>
444 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
445 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
446 // If there is an ANR, Dispatcher won't be idle because there are still events
447 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
448 // before checking if ANR was called.
449 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
450 // to provide it some time to act. 100ms seems reasonable.
451 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
452 const std::chrono::time_point start = std::chrono::steady_clock::now();
453 std::optional<T> token =
454 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
455 if (!token.has_value()) {
456 ADD_FAILURE() << "Did not receive the ANR callback";
457 return {};
458 }
459
460 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
461 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
462 // the dispatcher started counting before this function was called
463 if (std::chrono::abs(timeout - waited) > 100ms) {
464 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
465 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
466 << "ms, but waited "
467 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
468 << "ms instead";
469 }
470 return *token;
471 }
472
473 template <class T>
474 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
475 std::queue<T>& storage,
476 std::unique_lock<std::mutex>& lock,
477 std::condition_variable& condition)
478 REQUIRES(mLock) {
479 condition.wait_for(lock, timeout,
480 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
481 if (storage.empty()) {
482 ADD_FAILURE() << "Did not receive the expected callback";
483 return std::nullopt;
484 }
485 T item = storage.front();
486 storage.pop();
487 return std::make_optional(item);
488 }
489
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600490 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700491 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800492 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493 }
494
Prabir Pradhanedd96402022-02-15 01:46:16 -0800495 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
496 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700497 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800498 ASSERT_TRUE(pid.has_value());
499 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700500 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500501 }
502
Prabir Pradhanedd96402022-02-15 01:46:16 -0800503 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
504 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500505 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800506 ASSERT_TRUE(pid.has_value());
507 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500508 mNotifyAnr.notify_all();
509 }
510
511 void notifyNoFocusedWindowAnr(
512 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
513 std::scoped_lock lock(mLock);
514 mAnrApplications.push(applicationHandle);
515 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800516 }
517
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800518 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
519 std::scoped_lock lock(mLock);
520 mBrokenInputChannels.push(connectionToken);
521 mNotifyInputChannelBroken.notify_all();
522 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800523
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600524 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700525
Chris Yef59a2f42020-10-16 12:55:26 -0700526 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
527 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
528 const std::vector<float>& values) override {}
529
530 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
531 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000532
Chris Yefb552902021-02-03 17:18:37 -0800533 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
534
Prabir Pradhana41d2442023-04-20 21:30:40 +0000535 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800536
Prabir Pradhana41d2442023-04-20 21:30:40 +0000537 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700538 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000539 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700540 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000541 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
542 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800543 break;
544 }
545
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700546 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000547 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
548 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800549 break;
550 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700551 default: {
552 ADD_FAILURE() << "Should only filter keys or motions";
553 break;
554 }
Jackal Guof9696682018-10-05 12:23:23 +0800555 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556 return true;
557 }
558
Prabir Pradhana41d2442023-04-20 21:30:40 +0000559 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
560 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800561 // Clear intercept state when we handled the event.
562 mInterceptKeyTimeout = 0ms;
563 }
564 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600566 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567
Prabir Pradhana41d2442023-04-20 21:30:40 +0000568 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800569 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
570 // Clear intercept state so we could dispatch the event in next wake.
571 mInterceptKeyTimeout = 0ms;
572 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573 }
574
Prabir Pradhana41d2442023-04-20 21:30:40 +0000575 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
576 uint32_t) override {
577 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800578 }
579
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600580 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
581 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700582 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800583 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
584 * essentially a passthrough for notifySwitch.
585 */
Harry Cutts33476232023-01-30 19:57:29 +0000586 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587 }
588
Josep del Riob3981622023-04-18 15:49:45 +0000589 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
590 std::scoped_lock lock(mLock);
591 mPokedUserActivity = true;
592 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600594 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700595 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700596 mOnPointerDownToken = newToken;
597 }
598
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000599 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800600 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000601 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800602 mPointerCaptureChangedCondition.notify_all();
603 }
604
arthurhungf452d0b2021-01-06 00:19:52 +0800605 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
606 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800607 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800608 mDropTargetWindowToken = token;
609 }
610
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700611 void assertFilterInputEventWasCalledInternal(
612 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700613 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800614 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700615 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800616 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800617 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618};
619
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620// --- InputDispatcherTest ---
621
622class InputDispatcherTest : public testing::Test {
623protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000624 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700625 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000627 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000628 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
629 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800630 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000631 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700632 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 }
634
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000635 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700636 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000637 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700638 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800639 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700640
641 /**
642 * Used for debugging when writing the test
643 */
644 void dumpDispatcherState() {
645 std::string dump;
646 mDispatcher->dump(dump);
647 std::stringstream ss(dump);
648 std::string to;
649
650 while (std::getline(ss, to, '\n')) {
651 ALOGE("%s", to.c_str());
652 }
653 }
Vishnu Nair958da932020-08-21 17:12:37 -0700654
Chavi Weingarten847e8512023-03-29 00:26:09 +0000655 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700656 FocusRequest request;
657 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000658 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700659 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
660 request.displayId = window->getInfo()->displayId;
661 mDispatcher->setFocusedWindow(request);
662 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663};
664
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
666 KeyEvent event;
667
668 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800669 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
670 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600671 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
672 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800673 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000674 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000675 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800676 << "Should reject key events with undefined action.";
677
678 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800679 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
680 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600681 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800682 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000683 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000684 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685 << "Should reject key events with ACTION_MULTIPLE.";
686}
687
688TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
689 MotionEvent event;
690 PointerProperties pointerProperties[MAX_POINTERS + 1];
691 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800692 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800693 pointerProperties[i].clear();
694 pointerProperties[i].id = i;
695 pointerCoords[i].clear();
696 }
697
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800698 // Some constants commonly used below
699 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
700 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
701 constexpr int32_t metaState = AMETA_NONE;
702 constexpr MotionClassification classification = MotionClassification::NONE;
703
chaviw9eaa22c2020-07-01 16:21:27 -0700704 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800706 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700707 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
708 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700709 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
710 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700711 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800712 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000713 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000714 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800715 << "Should reject motion events with undefined action.";
716
717 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800719 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
720 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
721 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
722 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500723 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000725 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject motion events with pointer down index too large.";
728
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700730 AMOTION_EVENT_ACTION_POINTER_DOWN |
731 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700732 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
733 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700734 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500735 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000737 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000738 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800739 << "Should reject motion events with pointer down index too small.";
740
741 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800742 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800743 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
744 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
745 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
746 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500747 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800748 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000749 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000750 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800751 << "Should reject motion events with pointer up index too large.";
752
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700754 AMOTION_EVENT_ACTION_POINTER_UP |
755 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700756 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
757 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700758 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500759 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000761 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000762 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 << "Should reject motion events with pointer up index too small.";
764
765 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800766 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
767 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700768 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700769 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
770 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700771 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000773 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000774 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800775 << "Should reject motion events with 0 pointers.";
776
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with more than MAX_POINTERS pointers.";
787
788 // Rejects motion events with invalid pointer ids.
789 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800790 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
791 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700792 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700793 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
794 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700795 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800796 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000797 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000798 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800799 << "Should reject motion events with pointer ids less than 0.";
800
801 pointerProperties[0].id = MAX_POINTER_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*/ 1, 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 pointer ids greater than MAX_POINTER_ID.";
812
813 // Rejects motion events with duplicate pointer ids.
814 pointerProperties[0].id = 1;
815 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700821 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with duplicate pointer ids.";
826}
827
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800828/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
829
830TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
831 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000832 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800833 ASSERT_TRUE(mDispatcher->waitForIdle());
834
835 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
836}
837
838TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000839 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
840 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000841 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842
843 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
844 args.policyFlags |= POLICY_FLAG_TRUSTED;
845 mFakePolicy->assertNotifySwitchWasCalled(args);
846}
847
Arthur Hungb92218b2018-08-14 12:00:21 +0800848// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700849static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700850// Default input dispatching timeout if there is no focused application or paused window
851// from which to determine an appropriate dispatching timeout.
852static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
853 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
854 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800855
856class FakeApplicationHandle : public InputApplicationHandle {
857public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700858 FakeApplicationHandle() {
859 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700860 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500861 mInfo.dispatchingTimeoutMillis =
862 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700863 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800864 virtual ~FakeApplicationHandle() {}
865
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000866 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700867
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500868 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
869 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700870 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800871};
872
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800873class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800874public:
Garfield Tan15601662020-09-22 15:32:38 -0700875 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800876 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700877 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800878 }
879
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800880 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 InputEvent* event;
882 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
883 if (!consumeSeq) {
884 return nullptr;
885 }
886 finishEvent(*consumeSeq);
887 return event;
888 }
889
890 /**
891 * Receive an event without acknowledging it.
892 * Return the sequence number that could later be used to send finished signal.
893 */
894 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800895 uint32_t consumeSeq;
896 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800897
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800898 std::chrono::time_point start = std::chrono::steady_clock::now();
899 status_t status = WOULD_BLOCK;
900 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000901 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 &event);
903 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
904 if (elapsed > 100ms) {
905 break;
906 }
907 }
908
909 if (status == WOULD_BLOCK) {
910 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700911 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800912 }
913
914 if (status != OK) {
915 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917 }
918 if (event == nullptr) {
919 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700920 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 if (outEvent != nullptr) {
923 *outEvent = event;
924 }
925 return consumeSeq;
926 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800927
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700928 /**
929 * To be used together with "receiveEvent" to complete the consumption of an event.
930 */
931 void finishEvent(uint32_t consumeSeq) {
932 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
933 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800934 }
935
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000936 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
937 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
938 ASSERT_EQ(OK, status);
939 }
940
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700941 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000942 std::optional<int32_t> expectedDisplayId,
943 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800944 InputEvent* event = consume();
945
946 ASSERT_NE(nullptr, event) << mName.c_str()
947 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800948 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700949 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
950 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800951
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000952 if (expectedDisplayId.has_value()) {
953 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
954 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800955
Tiger Huang8664f8c2018-10-11 19:14:35 +0800956 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800958 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
959 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000960 if (expectedFlags.has_value()) {
961 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
962 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800963 break;
964 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800966 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000967 assertMotionAction(expectedAction, motionEvent.getAction());
968
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000969 if (expectedFlags.has_value()) {
970 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
971 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 break;
973 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700974 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100975 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
976 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800978 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000981 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
982 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800984 FAIL() << "Use 'consumeDragEvent' for DRAG events";
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800987 }
988
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800989 MotionEvent* consumeMotion() {
990 InputEvent* event = consume();
991
992 if (event == nullptr) {
993 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
994 return nullptr;
995 }
996
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 if (event->getType() != InputEventType::MOTION) {
998 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800999 return nullptr;
1000 }
1001 return static_cast<MotionEvent*>(event);
1002 }
1003
1004 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1005 MotionEvent* motionEvent = consumeMotion();
1006 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1007 ASSERT_THAT(*motionEvent, matcher);
1008 }
1009
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001010 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1011 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::FOCUS, event->getType())
1015 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001016
1017 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1018 << mName.c_str() << ": event displayId should always be NONE.";
1019
1020 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1021 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001022 }
1023
Prabir Pradhan99987712020-11-10 18:43:05 -08001024 void consumeCaptureEvent(bool hasCapture) {
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::CAPTURE, event->getType())
1029 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001030
1031 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1032 << mName.c_str() << ": event displayId should always be NONE.";
1033
1034 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1035 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1036 }
1037
arthurhungb89ccb02020-12-30 16:19:01 +08001038 void consumeDragEvent(bool isExiting, float x, float y) {
1039 const InputEvent* event = consume();
1040 ASSERT_NE(nullptr, event) << mName.c_str()
1041 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001042 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001043
1044 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1045 << mName.c_str() << ": event displayId should always be NONE.";
1046
1047 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1048 EXPECT_EQ(isExiting, dragEvent.isExiting());
1049 EXPECT_EQ(x, dragEvent.getX());
1050 EXPECT_EQ(y, dragEvent.getY());
1051 }
1052
Antonio Kantekf16f2832021-09-28 04:39:20 +00001053 void consumeTouchModeEvent(bool inTouchMode) {
1054 const InputEvent* event = consume();
1055 ASSERT_NE(nullptr, event) << mName.c_str()
1056 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001057 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1058 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001059
1060 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1061 << mName.c_str() << ": event displayId should always be NONE.";
1062 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1063 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1064 }
1065
chaviwd1c23182019-12-20 18:44:56 -08001066 void assertNoEvents() {
1067 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001068 if (event == nullptr) {
1069 return;
1070 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001071 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001072 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1073 ADD_FAILURE() << "Received key event "
1074 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001075 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001076 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1077 ADD_FAILURE() << "Received motion event "
1078 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001079 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001080 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1081 ADD_FAILURE() << "Received focus event, hasFocus = "
1082 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001083 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001084 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1085 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1086 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001087 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001088 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1089 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1090 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001091 }
1092 FAIL() << mName.c_str()
1093 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001094 }
1095
1096 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1097
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001098 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1099
chaviwd1c23182019-12-20 18:44:56 -08001100protected:
1101 std::unique_ptr<InputConsumer> mConsumer;
1102 PreallocatedInputEventFactory mEventFactory;
1103
1104 std::string mName;
1105};
1106
chaviw3277faf2021-05-19 16:45:23 -05001107class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001108public:
1109 static const int32_t WIDTH = 600;
1110 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001111
Chris Yea209fde2020-07-22 13:54:51 -07001112 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001113 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001114 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001115 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001116 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001117 base::Result<std::unique_ptr<InputChannel>> channel =
1118 dispatcher->createInputChannel(name);
1119 token = (*channel)->getConnectionToken();
1120 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001121 }
1122
1123 inputApplicationHandle->updateInfo();
1124 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1125
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001126 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001127 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001128 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001129 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001130 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.frameLeft = 0;
1132 mInfo.frameTop = 0;
1133 mInfo.frameRight = WIDTH;
1134 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001135 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001136 mInfo.globalScaleFactor = 1.0;
1137 mInfo.touchableRegion.clear();
1138 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001139 mInfo.ownerPid = WINDOW_PID;
1140 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001141 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001142 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001143 }
1144
Arthur Hungabbb9d82021-09-01 14:52:30 +00001145 sp<FakeWindowHandle> clone(
1146 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001147 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001148 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001149 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1150 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001151 return handle;
1152 }
1153
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001154 void setTouchable(bool touchable) {
1155 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1156 }
chaviwd1c23182019-12-20 18:44:56 -08001157
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001158 void setFocusable(bool focusable) {
1159 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1160 }
1161
1162 void setVisible(bool visible) {
1163 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1164 }
Vishnu Nair958da932020-08-21 17:12:37 -07001165
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001166 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001167 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001168 }
1169
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setPaused(bool paused) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1172 }
1173
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001174 void setPreventSplitting(bool preventSplitting) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001176 }
1177
1178 void setSlippery(bool slippery) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1180 }
1181
1182 void setWatchOutsideTouch(bool watchOutside) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1184 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001185
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001186 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1187
1188 void setInterceptsStylus(bool interceptsStylus) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1190 }
1191
1192 void setDropInput(bool dropInput) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1194 }
1195
1196 void setDropInputIfObscured(bool dropInputIfObscured) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1198 }
1199
1200 void setNoInputChannel(bool noInputChannel) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1202 }
1203
Josep del Riob3981622023-04-18 15:49:45 +00001204 void setDisableUserActivity(bool disableUserActivity) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1206 }
1207
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001208 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1209
chaviw3277faf2021-05-19 16:45:23 -05001210 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001211
Bernardo Rufino7393d172021-02-26 13:56:11 +00001212 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1213
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001214 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001215 mInfo.frameLeft = frame.left;
1216 mInfo.frameTop = frame.top;
1217 mInfo.frameRight = frame.right;
1218 mInfo.frameBottom = frame.bottom;
1219 mInfo.touchableRegion.clear();
1220 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001221
1222 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1223 ui::Transform translate;
1224 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1225 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001226 }
1227
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001228 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1229
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001230 void setIsWallpaper(bool isWallpaper) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1232 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001233
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001234 void setDupTouchToWallpaper(bool hasWallpaper) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1236 }
chaviwd1c23182019-12-20 18:44:56 -08001237
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001238 void setTrustedOverlay(bool trustedOverlay) {
1239 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1240 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001241
chaviw9eaa22c2020-07-01 16:21:27 -07001242 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1243 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1244 }
1245
1246 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001247
yunho.shinf4a80b82020-11-16 21:13:57 +09001248 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1249
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001250 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001251 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001252 }
1253
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001254 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001255 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001256 }
1257
Svet Ganov5d3bc372020-01-26 23:11:07 -08001258 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001259 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001260 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1261 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 }
1263
1264 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001265 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001266 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1267 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001268 }
1269
1270 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001271 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001272 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1273 }
1274
1275 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1276 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001277 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001278 expectedFlags);
1279 }
1280
Svet Ganov5d3bc372020-01-26 23:11:07 -08001281 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001282 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1283 int32_t expectedFlags = 0) {
1284 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1285 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001286 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 }
1288
1289 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001290 int32_t expectedFlags = 0) {
1291 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1292 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001294 }
1295
1296 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001297 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001298 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001299 expectedFlags);
1300 }
1301
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001302 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1303 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001304 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001305 expectedFlags);
1306 }
1307
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001308 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1309 int32_t expectedFlags = 0) {
1310 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001311 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001312 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001313 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1314 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1315 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1316 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1317 }
1318
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001319 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1323 }
1324
Prabir Pradhan99987712020-11-10 18:43:05 -08001325 void consumeCaptureEvent(bool hasCapture) {
1326 ASSERT_NE(mInputReceiver, nullptr)
1327 << "Cannot consume events from a window with no receiver";
1328 mInputReceiver->consumeCaptureEvent(hasCapture);
1329 }
1330
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001331 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1332 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001333 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001334 ASSERT_THAT(*motionEvent, matcher);
1335 }
1336
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001337 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001338 std::optional<int32_t> expectedDisplayId,
1339 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001340 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1341 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1342 expectedFlags);
1343 }
1344
arthurhungb89ccb02020-12-30 16:19:01 +08001345 void consumeDragEvent(bool isExiting, float x, float y) {
1346 mInputReceiver->consumeDragEvent(isExiting, x, y);
1347 }
1348
Antonio Kantekf16f2832021-09-28 04:39:20 +00001349 void consumeTouchModeEvent(bool inTouchMode) {
1350 ASSERT_NE(mInputReceiver, nullptr)
1351 << "Cannot consume events from a window with no receiver";
1352 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1353 }
1354
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001355 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001356 if (mInputReceiver == nullptr) {
1357 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1358 return std::nullopt;
1359 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001360 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001361 }
1362
1363 void finishEvent(uint32_t sequenceNum) {
1364 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1365 mInputReceiver->finishEvent(sequenceNum);
1366 }
1367
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001368 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1369 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1370 mInputReceiver->sendTimeline(inputEventId, timeline);
1371 }
1372
chaviwaf87b3e2019-10-01 16:59:28 -07001373 InputEvent* consume() {
1374 if (mInputReceiver == nullptr) {
1375 return nullptr;
1376 }
1377 return mInputReceiver->consume();
1378 }
1379
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001380 MotionEvent* consumeMotion() {
1381 InputEvent* event = consume();
1382 if (event == nullptr) {
1383 ADD_FAILURE() << "Consume failed : no event";
1384 return nullptr;
1385 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001386 if (event->getType() != InputEventType::MOTION) {
1387 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001388 return nullptr;
1389 }
1390 return static_cast<MotionEvent*>(event);
1391 }
1392
Arthur Hungb92218b2018-08-14 12:00:21 +08001393 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001394 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001395 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001396 return; // Can't receive events if the window does not have input channel
1397 }
1398 ASSERT_NE(nullptr, mInputReceiver)
1399 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001400 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001401 }
1402
chaviwaf87b3e2019-10-01 16:59:28 -07001403 sp<IBinder> getToken() { return mInfo.token; }
1404
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001405 const std::string& getName() { return mName; }
1406
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001407 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1408 mInfo.ownerPid = ownerPid;
1409 mInfo.ownerUid = ownerUid;
1410 }
1411
Prabir Pradhanedd96402022-02-15 01:46:16 -08001412 int32_t getPid() const { return mInfo.ownerPid; }
1413
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001414 void destroyReceiver() { mInputReceiver = nullptr; }
1415
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001416 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1417
chaviwd1c23182019-12-20 18:44:56 -08001418private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001419 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001420 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001421 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001422};
1423
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001424std::atomic<int32_t> FakeWindowHandle::sId{1};
1425
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001426static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001427 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001428 int32_t displayId = ADISPLAY_ID_NONE,
1429 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001430 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001431 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1432 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001433 KeyEvent event;
1434 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1435
1436 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001437 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001438 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1439 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001440
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001441 if (!allowKeyRepeat) {
1442 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1443 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001444 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001445 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001446}
1447
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001448static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001449 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001450 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001451}
1452
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001453// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1454// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1455// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001456static InputEventInjectionResult injectKeyDownNoRepeat(
1457 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001458 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001459 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001460 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001461}
1462
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001463static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001464 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001465 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001466}
1467
Garfield Tandf26e862020-07-01 20:18:19 -07001468class PointerBuilder {
1469public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001470 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001471 mProperties.clear();
1472 mProperties.id = id;
1473 mProperties.toolType = toolType;
1474 mCoords.clear();
1475 }
1476
1477 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1478
1479 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1480
1481 PointerBuilder& axis(int32_t axis, float value) {
1482 mCoords.setAxisValue(axis, value);
1483 return *this;
1484 }
1485
1486 PointerProperties buildProperties() const { return mProperties; }
1487
1488 PointerCoords buildCoords() const { return mCoords; }
1489
1490private:
1491 PointerProperties mProperties;
1492 PointerCoords mCoords;
1493};
1494
1495class MotionEventBuilder {
1496public:
1497 MotionEventBuilder(int32_t action, int32_t source) {
1498 mAction = action;
1499 mSource = source;
1500 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001501 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001502 }
1503
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001504 MotionEventBuilder& deviceId(int32_t deviceId) {
1505 mDeviceId = deviceId;
1506 return *this;
1507 }
1508
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001509 MotionEventBuilder& downTime(nsecs_t downTime) {
1510 mDownTime = downTime;
1511 return *this;
1512 }
1513
Garfield Tandf26e862020-07-01 20:18:19 -07001514 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1515 mEventTime = eventTime;
1516 return *this;
1517 }
1518
1519 MotionEventBuilder& displayId(int32_t displayId) {
1520 mDisplayId = displayId;
1521 return *this;
1522 }
1523
1524 MotionEventBuilder& actionButton(int32_t actionButton) {
1525 mActionButton = actionButton;
1526 return *this;
1527 }
1528
arthurhung6d4bed92021-03-17 11:59:33 +08001529 MotionEventBuilder& buttonState(int32_t buttonState) {
1530 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001531 return *this;
1532 }
1533
1534 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1535 mRawXCursorPosition = rawXCursorPosition;
1536 return *this;
1537 }
1538
1539 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1540 mRawYCursorPosition = rawYCursorPosition;
1541 return *this;
1542 }
1543
1544 MotionEventBuilder& pointer(PointerBuilder pointer) {
1545 mPointers.push_back(pointer);
1546 return *this;
1547 }
1548
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001549 MotionEventBuilder& addFlag(uint32_t flags) {
1550 mFlags |= flags;
1551 return *this;
1552 }
1553
Garfield Tandf26e862020-07-01 20:18:19 -07001554 MotionEvent build() {
1555 std::vector<PointerProperties> pointerProperties;
1556 std::vector<PointerCoords> pointerCoords;
1557 for (const PointerBuilder& pointer : mPointers) {
1558 pointerProperties.push_back(pointer.buildProperties());
1559 pointerCoords.push_back(pointer.buildCoords());
1560 }
1561
1562 // Set mouse cursor position for the most common cases to avoid boilerplate.
1563 if (mSource == AINPUT_SOURCE_MOUSE &&
1564 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1565 mPointers.size() == 1) {
1566 mRawXCursorPosition = pointerCoords[0].getX();
1567 mRawYCursorPosition = pointerCoords[0].getY();
1568 }
1569
1570 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001571 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001572 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001573 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001574 mButtonState, MotionClassification::NONE, identityTransform,
1575 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001576 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001577 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001578
1579 return event;
1580 }
1581
1582private:
1583 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001584 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001585 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001586 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001587 nsecs_t mEventTime;
1588 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1589 int32_t mActionButton{0};
1590 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001591 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001592 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1593 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1594
1595 std::vector<PointerBuilder> mPointers;
1596};
1597
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001598class MotionArgsBuilder {
1599public:
1600 MotionArgsBuilder(int32_t action, int32_t source) {
1601 mAction = action;
1602 mSource = source;
1603 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 mDownTime = mEventTime;
1605 }
1606
1607 MotionArgsBuilder& deviceId(int32_t deviceId) {
1608 mDeviceId = deviceId;
1609 return *this;
1610 }
1611
1612 MotionArgsBuilder& downTime(nsecs_t downTime) {
1613 mDownTime = downTime;
1614 return *this;
1615 }
1616
1617 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1618 mEventTime = eventTime;
1619 return *this;
1620 }
1621
1622 MotionArgsBuilder& displayId(int32_t displayId) {
1623 mDisplayId = displayId;
1624 return *this;
1625 }
1626
1627 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1628 mPolicyFlags = policyFlags;
1629 return *this;
1630 }
1631
1632 MotionArgsBuilder& actionButton(int32_t actionButton) {
1633 mActionButton = actionButton;
1634 return *this;
1635 }
1636
1637 MotionArgsBuilder& buttonState(int32_t buttonState) {
1638 mButtonState = buttonState;
1639 return *this;
1640 }
1641
1642 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1643 mRawXCursorPosition = rawXCursorPosition;
1644 return *this;
1645 }
1646
1647 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1648 mRawYCursorPosition = rawYCursorPosition;
1649 return *this;
1650 }
1651
1652 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1653 mPointers.push_back(pointer);
1654 return *this;
1655 }
1656
1657 MotionArgsBuilder& addFlag(uint32_t flags) {
1658 mFlags |= flags;
1659 return *this;
1660 }
1661
1662 NotifyMotionArgs build() {
1663 std::vector<PointerProperties> pointerProperties;
1664 std::vector<PointerCoords> pointerCoords;
1665 for (const PointerBuilder& pointer : mPointers) {
1666 pointerProperties.push_back(pointer.buildProperties());
1667 pointerCoords.push_back(pointer.buildCoords());
1668 }
1669
1670 // Set mouse cursor position for the most common cases to avoid boilerplate.
1671 if (mSource == AINPUT_SOURCE_MOUSE &&
1672 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1673 mPointers.size() == 1) {
1674 mRawXCursorPosition = pointerCoords[0].getX();
1675 mRawYCursorPosition = pointerCoords[0].getY();
1676 }
1677
1678 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1679 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1680 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1681 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1682 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1683 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1684
1685 return args;
1686 }
1687
1688private:
1689 int32_t mAction;
1690 int32_t mDeviceId = DEVICE_ID;
1691 int32_t mSource;
1692 nsecs_t mDownTime;
1693 nsecs_t mEventTime;
1694 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1695 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1696 int32_t mActionButton{0};
1697 int32_t mButtonState{0};
1698 int32_t mFlags{0};
1699 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1700 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1701
1702 std::vector<PointerBuilder> mPointers;
1703};
1704
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001705static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001706 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001707 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001708 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1709 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1710 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1711 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001712}
1713
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001714static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001715 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001716 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001717 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001718 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1719 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001720 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001721 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1722 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001723 MotionEvent event = MotionEventBuilder(action, source)
1724 .displayId(displayId)
1725 .eventTime(eventTime)
1726 .rawXCursorPosition(cursorPosition.x)
1727 .rawYCursorPosition(cursorPosition.y)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001728 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001729 .x(position.x)
1730 .y(position.y))
1731 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001732
1733 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001734 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1735 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001736}
1737
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001738static InputEventInjectionResult injectMotionDown(
1739 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1740 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001741 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001742}
1743
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001744static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 int32_t source, int32_t displayId,
1746 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001747 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001748}
1749
Jackal Guof9696682018-10-05 12:23:23 +08001750static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1751 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1752 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001753 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001754 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1755 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001756
1757 return args;
1758}
1759
Josep del Riob3981622023-04-18 15:49:45 +00001760static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1761 int32_t displayId = ADISPLAY_ID_NONE) {
1762 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1763 // Define a valid key event.
1764 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1765 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1766 currentTime);
1767
1768 return args;
1769}
1770
1771static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1772 int32_t displayId = ADISPLAY_ID_NONE) {
1773 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1774 // Define a valid key event.
1775 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1776 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1777 AMETA_NONE, currentTime);
1778
1779 return args;
1780}
1781
Prabir Pradhan678438e2023-04-13 19:32:51 +00001782[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1783 int32_t displayId,
1784 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001785 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001786 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1787 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1788 }
1789
chaviwd1c23182019-12-20 18:44:56 -08001790 PointerProperties pointerProperties[pointerCount];
1791 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001792
chaviwd1c23182019-12-20 18:44:56 -08001793 for (size_t i = 0; i < pointerCount; i++) {
1794 pointerProperties[i].clear();
1795 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001796 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001797
chaviwd1c23182019-12-20 18:44:56 -08001798 pointerCoords[i].clear();
1799 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1800 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1801 }
Jackal Guof9696682018-10-05 12:23:23 +08001802
1803 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1804 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001805 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001806 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1807 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001808 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1809 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001810 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1811 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001812
1813 return args;
1814}
1815
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001816static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1817 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1818}
1819
chaviwd1c23182019-12-20 18:44:56 -08001820static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1821 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1822}
1823
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001824static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1825 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001826 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001827}
1828
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001829/**
1830 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1831 * broken channel.
1832 */
1833TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1835 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle>::make(application, mDispatcher,
1837 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001838
1839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1840
1841 // Window closes its channel, but the window remains.
1842 window->destroyReceiver();
1843 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1844}
1845
Arthur Hungb92218b2018-08-14 12:00:21 +08001846TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001848 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1849 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001850
Arthur Hung72d8dc32020-03-28 00:48:39 +00001851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1853 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001855
1856 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001857 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001858}
1859
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001860TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1863 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001864
1865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1866 // Inject a MotionEvent to an unknown display.
1867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1869 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1870
1871 // Window should receive motion event.
1872 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1873}
1874
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001875/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001876 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001877 * This test serves as a sanity check for the next test, where setInputWindows is
1878 * called twice.
1879 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001880TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1883 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001884 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001885
1886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001888 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1889 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001891
1892 // Window should receive motion event.
1893 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1894}
1895
1896/**
1897 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001898 */
1899TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001901 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1902 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001903 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001904
1905 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001908 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1909 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001911
1912 // Window should receive motion event.
1913 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1914}
1915
Arthur Hungb92218b2018-08-14 12:00:21 +08001916// The foreground window should receive the first touch down event.
1917TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001919 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001920 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001921 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001922 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001923
Arthur Hung72d8dc32020-03-28 00:48:39 +00001924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1926 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001928
1929 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001930 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001931 windowSecond->assertNoEvents();
1932}
1933
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934/**
1935 * Two windows: A top window, and a wallpaper behind the window.
1936 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1937 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001938 * 1. foregroundWindow <-- dup touch to wallpaper
1939 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940 */
1941TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1943 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001944 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001945 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001948 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001949
1950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1952 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1953 {100, 200}))
1954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1955
1956 // Both foreground window and its wallpaper should receive the touch down
1957 foregroundWindow->consumeMotionDown();
1958 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1959
1960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1961 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1962 ADISPLAY_ID_DEFAULT, {110, 200}))
1963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1964
1965 foregroundWindow->consumeMotionMove();
1966 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1967
1968 // Now the foreground window goes away, but the wallpaper stays
1969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1970 foregroundWindow->consumeMotionCancel();
1971 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1972 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973}
1974
1975/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001976 * Two fingers down on the window, and lift off the first finger.
1977 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1978 * contains a single pointer.
1979 */
1980TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1982 sp<FakeWindowHandle> window =
1983 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1984
1985 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001986 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1988 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1989 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001990 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001991 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1992 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1993 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1994 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001995 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001996 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1997 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1998 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1999 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002000 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2001 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2002 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2003
2004 // Remove the window. The gesture should be canceled
2005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2006 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
2007 window->consumeMotionEvent(
2008 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
2009}
2010
2011/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002012 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
2013 * with the following differences:
2014 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
2015 * clean up the connection.
2016 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
2017 * Ensure that there's no crash in the dispatcher.
2018 */
2019TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
2020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2021 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002022 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002023 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002024 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002025 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002026 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002027
2028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2030 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2031 {100, 200}))
2032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2033
2034 // Both foreground window and its wallpaper should receive the touch down
2035 foregroundWindow->consumeMotionDown();
2036 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2037
2038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2039 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2040 ADISPLAY_ID_DEFAULT, {110, 200}))
2041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2042
2043 foregroundWindow->consumeMotionMove();
2044 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2045
2046 // Wallpaper closes its channel, but the window remains.
2047 wallpaperWindow->destroyReceiver();
2048 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2049
2050 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2051 // is no longer valid.
2052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2053 foregroundWindow->consumeMotionCancel();
2054}
2055
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056class ShouldSplitTouchFixture : public InputDispatcherTest,
2057 public ::testing::WithParamInterface<bool> {};
2058INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2059 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002060/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002061 * A single window that receives touch (on top), and a wallpaper window underneath it.
2062 * The top window gets a multitouch gesture.
2063 * Ensure that wallpaper gets the same gesture.
2064 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002067 sp<FakeWindowHandle> foregroundWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2069 foregroundWindow->setDupTouchToWallpaper(true);
2070 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002071
2072 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002073 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002074 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002075
Arthur Hungc539dbb2022-12-08 07:45:36 +00002076 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002077
2078 // Touch down on top window
2079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2080 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2081 {100, 100}))
2082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2083
2084 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002085 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002086 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2087
2088 // Second finger down on the top window
2089 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002090 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002091 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002092 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2093 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 .build();
2095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2096 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2097 InputEventInjectionSync::WAIT_FOR_RESULT))
2098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2099
Harry Cutts33476232023-01-30 19:57:29 +00002100 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2101 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002103
2104 const MotionEvent secondFingerUpEvent =
2105 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2106 .displayId(ADISPLAY_ID_DEFAULT)
2107 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002108 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2109 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002110 .build();
2111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2112 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2113 InputEventInjectionSync::WAIT_FOR_RESULT))
2114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2115 foregroundWindow->consumeMotionPointerUp(0);
2116 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2117
2118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002119 injectMotionEvent(mDispatcher,
2120 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2121 AINPUT_SOURCE_TOUCHSCREEN)
2122 .displayId(ADISPLAY_ID_DEFAULT)
2123 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2124 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002125 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002126 .x(100)
2127 .y(100))
2128 .build(),
2129 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2131 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2132 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002133}
2134
2135/**
2136 * Two windows: a window on the left and window on the right.
2137 * A third window, wallpaper, is behind both windows, and spans both top windows.
2138 * The first touch down goes to the left window. A second pointer touches down on the right window.
2139 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2140 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2141 * ACTION_POINTER_DOWN(1).
2142 */
2143TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2145 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002146 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002147 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002148 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002149
2150 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002151 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002152 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002153 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002154
2155 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002156 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002157 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002158 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002159
2160 mDispatcher->setInputWindows(
2161 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2162
2163 // Touch down on left window
2164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2165 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2166 {100, 100}))
2167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2168
2169 // Both foreground window and its wallpaper should receive the touch down
2170 leftWindow->consumeMotionDown();
2171 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2172
2173 // Second finger down on the right window
2174 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002175 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002176 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002177 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2178 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002179 .build();
2180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2181 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2182 InputEventInjectionSync::WAIT_FOR_RESULT))
2183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2184
2185 leftWindow->consumeMotionMove();
2186 // Since the touch is split, right window gets ACTION_DOWN
2187 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002188 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002189 expectedWallpaperFlags);
2190
2191 // Now, leftWindow, which received the first finger, disappears.
2192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2193 leftWindow->consumeMotionCancel();
2194 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2195 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2196
2197 // The pointer that's still down on the right window moves, and goes to the right window only.
2198 // As far as the dispatcher's concerned though, both pointers are still present.
2199 const MotionEvent secondFingerMoveEvent =
2200 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2201 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002202 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2203 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002204 .build();
2205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2206 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2207 InputEventInjectionSync::WAIT_FOR_RESULT));
2208 rightWindow->consumeMotionMove();
2209
2210 leftWindow->assertNoEvents();
2211 rightWindow->assertNoEvents();
2212 wallpaperWindow->assertNoEvents();
2213}
2214
Arthur Hungc539dbb2022-12-08 07:45:36 +00002215/**
2216 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2217 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2218 * The right window should receive ACTION_DOWN.
2219 */
2220TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002222 sp<FakeWindowHandle> leftWindow =
2223 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2224 leftWindow->setFrame(Rect(0, 0, 200, 200));
2225 leftWindow->setDupTouchToWallpaper(true);
2226 leftWindow->setSlippery(true);
2227
2228 sp<FakeWindowHandle> rightWindow =
2229 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2230 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002231
2232 sp<FakeWindowHandle> wallpaperWindow =
2233 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2234 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002235
Arthur Hungc539dbb2022-12-08 07:45:36 +00002236 mDispatcher->setInputWindows(
2237 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002238
Arthur Hungc539dbb2022-12-08 07:45:36 +00002239 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2241 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002242 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002244
2245 // Both foreground window and its wallpaper should receive the touch down
2246 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002247 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2248
Arthur Hungc539dbb2022-12-08 07:45:36 +00002249 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002251 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2252 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2254
Arthur Hungc539dbb2022-12-08 07:45:36 +00002255 leftWindow->consumeMotionCancel();
2256 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2257 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002258}
2259
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002260/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002261 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2262 * interactive, it might stop sending this flag.
2263 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2264 * to have a consistent input stream.
2265 *
2266 * Test procedure:
2267 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2268 * DOWN (new gesture).
2269 *
2270 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2271 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2272 *
2273 * We technically just need a single window here, but we are using two windows (spy on top and a
2274 * regular window below) to emulate the actual situation where it happens on the device.
2275 */
2276TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2278 sp<FakeWindowHandle> spyWindow =
2279 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2280 spyWindow->setFrame(Rect(0, 0, 200, 200));
2281 spyWindow->setTrustedOverlay(true);
2282 spyWindow->setSpy(true);
2283
2284 sp<FakeWindowHandle> window =
2285 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2286 window->setFrame(Rect(0, 0, 200, 200));
2287
2288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2289 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002290
2291 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002292 mDispatcher->notifyMotion(
2293 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2294 .deviceId(touchDeviceId)
2295 .policyFlags(DEFAULT_POLICY_FLAGS)
2296 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2297 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002298
Prabir Pradhan678438e2023-04-13 19:32:51 +00002299 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2300 .deviceId(touchDeviceId)
2301 .policyFlags(DEFAULT_POLICY_FLAGS)
2302 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2303 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2304 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002305 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2306 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2307 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2308 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2309
2310 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002311 mDispatcher->notifyMotion(
2312 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2313 .deviceId(touchDeviceId)
2314 .policyFlags(0)
2315 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2316 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2317 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002318 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2319 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2320
2321 // We don't need to reset the device to reproduce the issue, but the reset event typically
2322 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002323 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002324
2325 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002326 mDispatcher->notifyMotion(
2327 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2328 .deviceId(touchDeviceId)
2329 .policyFlags(DEFAULT_POLICY_FLAGS)
2330 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2331 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002332 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2333 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2334
2335 // No more events
2336 spyWindow->assertNoEvents();
2337 window->assertNoEvents();
2338}
2339
2340/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002341 * Two windows: a window on the left and a window on the right.
2342 * Mouse is hovered from the right window into the left window.
2343 * Next, we tap on the left window, where the cursor was last seen.
2344 * The second tap is done onto the right window.
2345 * The mouse and tap are from two different devices.
2346 * We technically don't need to set the downtime / eventtime for these events, but setting these
2347 * explicitly helps during debugging.
2348 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2349 * In the buggy implementation, a tap on the right window would cause a crash.
2350 */
2351TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2353 sp<FakeWindowHandle> leftWindow =
2354 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2355 leftWindow->setFrame(Rect(0, 0, 200, 200));
2356
2357 sp<FakeWindowHandle> rightWindow =
2358 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2359 rightWindow->setFrame(Rect(200, 0, 400, 200));
2360
2361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2362 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2363 // stale.
2364 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2365 const int32_t mouseDeviceId = 6;
2366 const int32_t touchDeviceId = 4;
2367 // Move the cursor from right
2368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2369 injectMotionEvent(mDispatcher,
2370 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2371 AINPUT_SOURCE_MOUSE)
2372 .deviceId(mouseDeviceId)
2373 .downTime(baseTime + 10)
2374 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002375 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002376 .x(300)
2377 .y(100))
2378 .build()));
2379 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2380
2381 // .. to the left window
2382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2383 injectMotionEvent(mDispatcher,
2384 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2385 AINPUT_SOURCE_MOUSE)
2386 .deviceId(mouseDeviceId)
2387 .downTime(baseTime + 10)
2388 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002389 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002390 .x(110)
2391 .y(100))
2392 .build()));
2393 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2394 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2395 // Now tap the left window
2396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2397 injectMotionEvent(mDispatcher,
2398 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2399 AINPUT_SOURCE_TOUCHSCREEN)
2400 .deviceId(touchDeviceId)
2401 .downTime(baseTime + 40)
2402 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002403 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002404 .x(100)
2405 .y(100))
2406 .build()));
2407 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2408 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2409
2410 // release tap
2411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2412 injectMotionEvent(mDispatcher,
2413 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2414 AINPUT_SOURCE_TOUCHSCREEN)
2415 .deviceId(touchDeviceId)
2416 .downTime(baseTime + 40)
2417 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002418 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002419 .x(100)
2420 .y(100))
2421 .build()));
2422 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2423
2424 // Tap the window on the right
2425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2426 injectMotionEvent(mDispatcher,
2427 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2428 AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .downTime(baseTime + 60)
2431 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002432 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002433 .x(300)
2434 .y(100))
2435 .build()));
2436 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2437
2438 // release tap
2439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2440 injectMotionEvent(mDispatcher,
2441 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2442 AINPUT_SOURCE_TOUCHSCREEN)
2443 .deviceId(touchDeviceId)
2444 .downTime(baseTime + 60)
2445 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002446 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002447 .x(300)
2448 .y(100))
2449 .build()));
2450 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2451
2452 // No more events
2453 leftWindow->assertNoEvents();
2454 rightWindow->assertNoEvents();
2455}
2456
2457/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002458 * Two windows: a window on the left and a window on the right.
2459 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2460 * down. Then, on the left window, also place second touch pointer down.
2461 * This test tries to reproduce a crash.
2462 * In the buggy implementation, second pointer down on the left window would cause a crash.
2463 */
2464TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2466 sp<FakeWindowHandle> leftWindow =
2467 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2468 leftWindow->setFrame(Rect(0, 0, 200, 200));
2469
2470 sp<FakeWindowHandle> rightWindow =
2471 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2472 rightWindow->setFrame(Rect(200, 0, 400, 200));
2473
2474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2475
2476 const int32_t touchDeviceId = 4;
2477 const int32_t mouseDeviceId = 6;
2478 NotifyMotionArgs args;
2479
2480 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2482 .deviceId(mouseDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2484 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002485 leftWindow->consumeMotionEvent(
2486 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2487
2488 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2490 .deviceId(mouseDeviceId)
2491 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494
2495 leftWindow->consumeMotionEvent(
2496 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2497 leftWindow->consumeMotionEvent(
2498 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2499
Prabir Pradhan678438e2023-04-13 19:32:51 +00002500 mDispatcher->notifyMotion(
2501 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2502 .deviceId(mouseDeviceId)
2503 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2504 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2505 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2506 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002507 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2508
2509 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2511 .deviceId(touchDeviceId)
2512 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2513 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002514 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2515
2516 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2517
2518 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002519 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2520 .deviceId(touchDeviceId)
2521 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2522 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2523 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002524 leftWindow->consumeMotionEvent(
2525 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2526 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2527 // current implementation.
2528 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2529 rightWindow->consumeMotionEvent(
2530 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2531
2532 leftWindow->assertNoEvents();
2533 rightWindow->assertNoEvents();
2534}
2535
2536/**
2537 * On a single window, use two different devices: mouse and touch.
2538 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2539 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2540 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2541 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2542 * represent a new gesture.
2543 */
2544TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2546 sp<FakeWindowHandle> window =
2547 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2548 window->setFrame(Rect(0, 0, 400, 400));
2549
2550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2551
2552 const int32_t touchDeviceId = 4;
2553 const int32_t mouseDeviceId = 6;
2554 NotifyMotionArgs args;
2555
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002556 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2558 .deviceId(touchDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2560 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002561 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002562 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2563 .deviceId(touchDeviceId)
2564 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2565 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2566 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002567 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002568 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2569 .deviceId(touchDeviceId)
2570 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2571 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2572 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002573 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2574 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2575 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2576
2577 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2579 .deviceId(mouseDeviceId)
2580 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2581 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2582 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002583
2584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002585 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002586 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2587
Prabir Pradhan678438e2023-04-13 19:32:51 +00002588 mDispatcher->notifyMotion(
2589 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2590 .deviceId(mouseDeviceId)
2591 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2592 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2593 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2594 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002595 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2596
2597 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002598 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2599 .deviceId(touchDeviceId)
2600 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2601 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2602 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002603 // The pointer_down event should be ignored
2604 window->assertNoEvents();
2605}
2606
2607/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002608 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2609 * the injected event.
2610 */
2611TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2612 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2613 sp<FakeWindowHandle> window =
2614 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2615 window->setFrame(Rect(0, 0, 400, 400));
2616
2617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2618
2619 const int32_t touchDeviceId = 4;
2620 NotifyMotionArgs args;
2621 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2622 // completion.
2623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2624 injectMotionEvent(mDispatcher,
2625 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2626 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002627 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002628 .x(50)
2629 .y(50))
2630 .build()));
2631 window->consumeMotionEvent(
2632 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2633
2634 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2635 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002636 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2637 .deviceId(touchDeviceId)
2638 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2639 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002640
2641 window->consumeMotionEvent(
2642 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2643 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2644}
2645
2646/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002647 * This test is similar to the test above, but the sequence of injected events is different.
2648 *
2649 * Two windows: a window on the left and a window on the right.
2650 * Mouse is hovered over the left window.
2651 * Next, we tap on the left window, where the cursor was last seen.
2652 *
2653 * After that, we inject one finger down onto the right window, and then a second finger down onto
2654 * the left window.
2655 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2656 * window (first), and then another on the left window (second).
2657 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2658 * In the buggy implementation, second finger down on the left window would cause a crash.
2659 */
2660TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2662 sp<FakeWindowHandle> leftWindow =
2663 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2664 leftWindow->setFrame(Rect(0, 0, 200, 200));
2665
2666 sp<FakeWindowHandle> rightWindow =
2667 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2668 rightWindow->setFrame(Rect(200, 0, 400, 200));
2669
2670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2671
2672 const int32_t mouseDeviceId = 6;
2673 const int32_t touchDeviceId = 4;
2674 // Hover over the left window. Keep the cursor there.
2675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2676 injectMotionEvent(mDispatcher,
2677 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2678 AINPUT_SOURCE_MOUSE)
2679 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002680 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002681 .x(50)
2682 .y(50))
2683 .build()));
2684 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2685
2686 // Tap on left window
2687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2688 injectMotionEvent(mDispatcher,
2689 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2690 AINPUT_SOURCE_TOUCHSCREEN)
2691 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002692 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002693 .x(100)
2694 .y(100))
2695 .build()));
2696
2697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2698 injectMotionEvent(mDispatcher,
2699 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2700 AINPUT_SOURCE_TOUCHSCREEN)
2701 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002702 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002703 .x(100)
2704 .y(100))
2705 .build()));
2706 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2707 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2708 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2709
2710 // First finger down on right window
2711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2712 injectMotionEvent(mDispatcher,
2713 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2714 AINPUT_SOURCE_TOUCHSCREEN)
2715 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002716 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002717 .x(300)
2718 .y(100))
2719 .build()));
2720 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2721
2722 // Second finger down on the left window
2723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2724 injectMotionEvent(mDispatcher,
2725 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2726 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002727 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002728 .x(300)
2729 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002730 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002731 .x(100)
2732 .y(100))
2733 .build()));
2734 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2735 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2736
2737 // No more events
2738 leftWindow->assertNoEvents();
2739 rightWindow->assertNoEvents();
2740}
2741
2742/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002743 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2744 * While the touch is down, new hover events from the stylus device should be ignored. After the
2745 * touch is gone, stylus hovering should start working again.
2746 */
2747TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2749 sp<FakeWindowHandle> window =
2750 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2751 window->setFrame(Rect(0, 0, 200, 200));
2752
2753 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2754
2755 const int32_t stylusDeviceId = 5;
2756 const int32_t touchDeviceId = 4;
2757 // Start hovering with stylus
2758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2759 injectMotionEvent(mDispatcher,
2760 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2761 AINPUT_SOURCE_STYLUS)
2762 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002763 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002764 .x(50)
2765 .y(50))
2766 .build()));
2767 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2768
2769 // Finger down on the window
2770 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2771 injectMotionEvent(mDispatcher,
2772 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2773 AINPUT_SOURCE_TOUCHSCREEN)
2774 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002775 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002776 .x(100)
2777 .y(100))
2778 .build()));
2779 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2780 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2781
2782 // Try to continue hovering with stylus. Since we are already down, injection should fail
2783 ASSERT_EQ(InputEventInjectionResult::FAILED,
2784 injectMotionEvent(mDispatcher,
2785 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2786 AINPUT_SOURCE_STYLUS)
2787 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002788 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002789 .x(50)
2790 .y(50))
2791 .build()));
2792 // No event should be sent. This event should be ignored because a pointer from another device
2793 // is already down.
2794
2795 // Lift up the finger
2796 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2797 injectMotionEvent(mDispatcher,
2798 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2799 AINPUT_SOURCE_TOUCHSCREEN)
2800 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002801 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002802 .x(100)
2803 .y(100))
2804 .build()));
2805 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2806
2807 // Now that the touch is gone, stylus hovering should start working again
2808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2809 injectMotionEvent(mDispatcher,
2810 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2811 AINPUT_SOURCE_STYLUS)
2812 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002813 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002814 .x(50)
2815 .y(50))
2816 .build()));
2817 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2818 // No more events
2819 window->assertNoEvents();
2820}
2821
2822/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002823 * A spy window above a window with no input channel.
2824 * Start hovering with a stylus device, and then tap with it.
2825 * Ensure spy window receives the entire sequence.
2826 */
2827TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2829 sp<FakeWindowHandle> spyWindow =
2830 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2831 spyWindow->setFrame(Rect(0, 0, 200, 200));
2832 spyWindow->setTrustedOverlay(true);
2833 spyWindow->setSpy(true);
2834 sp<FakeWindowHandle> window =
2835 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2836 window->setNoInputChannel(true);
2837 window->setFrame(Rect(0, 0, 200, 200));
2838
2839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2840
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002841 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2843 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2844 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002845 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2846 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2848 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2849 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002850 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2851
2852 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2855 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002856 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2857
2858 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2860 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2861 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002862 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2863
2864 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2866 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2867 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002868 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2869 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2871 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2872 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002873 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2874
2875 // No more events
2876 spyWindow->assertNoEvents();
2877 window->assertNoEvents();
2878}
2879
2880/**
2881 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2882 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2883 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2884 * While the mouse is down, new move events from the touch device should be ignored.
2885 */
2886TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2888 sp<FakeWindowHandle> spyWindow =
2889 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2890 spyWindow->setFrame(Rect(0, 0, 200, 200));
2891 spyWindow->setTrustedOverlay(true);
2892 spyWindow->setSpy(true);
2893 sp<FakeWindowHandle> window =
2894 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2895 window->setFrame(Rect(0, 0, 200, 200));
2896
2897 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2898
2899 const int32_t mouseDeviceId = 7;
2900 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002901
2902 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2904 .deviceId(mouseDeviceId)
2905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2906 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002907 spyWindow->consumeMotionEvent(
2908 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2909 window->consumeMotionEvent(
2910 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2911
2912 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2914 .deviceId(touchDeviceId)
2915 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2916 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002917 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2918 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2919 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2920 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2921
Prabir Pradhan678438e2023-04-13 19:32:51 +00002922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2923 .deviceId(touchDeviceId)
2924 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2925 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002926 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2927 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2928
2929 // Pilfer the stream
2930 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2931 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2932
Prabir Pradhan678438e2023-04-13 19:32:51 +00002933 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2934 .deviceId(touchDeviceId)
2935 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2936 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002937 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2938
2939 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002940 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2941 .deviceId(mouseDeviceId)
2942 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2943 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2944 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002945
2946 spyWindow->consumeMotionEvent(
2947 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2948 spyWindow->consumeMotionEvent(
2949 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2950 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2951
Prabir Pradhan678438e2023-04-13 19:32:51 +00002952 mDispatcher->notifyMotion(
2953 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2954 .deviceId(mouseDeviceId)
2955 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2956 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2957 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2958 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002959 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2960 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2961
2962 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2964 .deviceId(mouseDeviceId)
2965 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2967 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002968 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2969 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2970
2971 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002972 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2973 .deviceId(touchDeviceId)
2974 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2975 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002976
2977 // No more events
2978 spyWindow->assertNoEvents();
2979 window->assertNoEvents();
2980}
2981
2982/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002983 * On the display, have a single window, and also an area where there's no window.
2984 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2985 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2986 */
2987TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2989 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002990 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002991
2992 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002993
2994 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002995 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002996
2997 mDispatcher->waitForIdle();
2998 window->assertNoEvents();
2999
3000 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003001 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003002 mDispatcher->waitForIdle();
3003 window->consumeMotionDown();
3004}
3005
3006/**
3007 * Same test as above, but instead of touching the empty space, the first touch goes to
3008 * non-touchable window.
3009 */
3010TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3012 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003013 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003014 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3015 window1->setTouchable(false);
3016 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003017 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003018 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3019
3020 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3021
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003022 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003023 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003024
3025 mDispatcher->waitForIdle();
3026 window1->assertNoEvents();
3027 window2->assertNoEvents();
3028
3029 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003030 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003031 mDispatcher->waitForIdle();
3032 window2->consumeMotionDown();
3033}
3034
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003035/**
3036 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3037 * to the event time of the first ACTION_DOWN sent to the particular window.
3038 */
3039TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3040 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3041 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003042 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003043 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3044 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003045 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003046 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3047
3048 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3049
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003050 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003051 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003052
3053 mDispatcher->waitForIdle();
3054 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003055 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003056 window2->assertNoEvents();
3057 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3058 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3059 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3060
3061 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003062 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003063 mDispatcher->waitForIdle();
3064 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003065 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003066 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3067 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3068 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3069 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3070
3071 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003072 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003073 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003074 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003075
3076 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003077 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003078 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003079 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003080
3081 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3082 window1->consumeMotionMove();
3083 window1->assertNoEvents();
3084
3085 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003086 mDispatcher->notifyMotion(
3087 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003088 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003089 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003090
Prabir Pradhan678438e2023-04-13 19:32:51 +00003091 mDispatcher->notifyMotion(
3092 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003093 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003094 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003095}
3096
Garfield Tandf26e862020-07-01 20:18:19 -07003097TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003099 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003100 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003101 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003102 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003103 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003104 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003105
3106 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3107
3108 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3109
3110 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003112 injectMotionEvent(mDispatcher,
3113 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3114 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003115 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003116 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003117 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003118
3119 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003121 injectMotionEvent(mDispatcher,
3122 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3123 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003124 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003125 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003126 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3127 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003128
3129 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003131 injectMotionEvent(mDispatcher,
3132 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3133 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003135 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3137 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003138
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003140 injectMotionEvent(mDispatcher,
3141 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3142 AINPUT_SOURCE_MOUSE)
3143 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3144 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003145 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003146 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003147 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003148
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003150 injectMotionEvent(mDispatcher,
3151 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3152 AINPUT_SOURCE_MOUSE)
3153 .buttonState(0)
3154 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003155 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003156 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003157 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003158
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003160 injectMotionEvent(mDispatcher,
3161 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3162 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003163 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003164 .build()));
3165 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3166
3167 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003169 injectMotionEvent(mDispatcher,
3170 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3171 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003172 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003173 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003174 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003175
3176 // No more events
3177 windowLeft->assertNoEvents();
3178 windowRight->assertNoEvents();
3179}
3180
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003181/**
3182 * Put two fingers down (and don't release them) and click the mouse button.
3183 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3184 * currently active gesture should be canceled, and the new one should proceed.
3185 */
3186TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3188 sp<FakeWindowHandle> window =
3189 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3190 window->setFrame(Rect(0, 0, 600, 800));
3191
3192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3193
3194 const int32_t touchDeviceId = 4;
3195 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003196
3197 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3199 .deviceId(touchDeviceId)
3200 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3201 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003202
Prabir Pradhan678438e2023-04-13 19:32:51 +00003203 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3204 .deviceId(touchDeviceId)
3205 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3206 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3207 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003208 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3209 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3210
3211 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3213 .deviceId(mouseDeviceId)
3214 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3215 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3216 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003217 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3218 WithPointerCount(2u)));
3219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3220
Prabir Pradhan678438e2023-04-13 19:32:51 +00003221 mDispatcher->notifyMotion(
3222 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3223 .deviceId(mouseDeviceId)
3224 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3225 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3226 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3227 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003228 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3229
3230 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3231 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3233 .deviceId(touchDeviceId)
3234 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3235 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3236 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003237 window->assertNoEvents();
3238}
3239
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003240TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3242
3243 sp<FakeWindowHandle> spyWindow =
3244 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3245 spyWindow->setFrame(Rect(0, 0, 600, 800));
3246 spyWindow->setTrustedOverlay(true);
3247 spyWindow->setSpy(true);
3248 sp<FakeWindowHandle> window =
3249 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3250 window->setFrame(Rect(0, 0, 600, 800));
3251
3252 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3253 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3254
3255 // Send mouse cursor to the window
3256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3257 injectMotionEvent(mDispatcher,
3258 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3259 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003260 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003261 .x(100)
3262 .y(100))
3263 .build()));
3264
3265 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3266 WithSource(AINPUT_SOURCE_MOUSE)));
3267 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3268 WithSource(AINPUT_SOURCE_MOUSE)));
3269
3270 window->assertNoEvents();
3271 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003272}
3273
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003274TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3276
3277 sp<FakeWindowHandle> spyWindow =
3278 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3279 spyWindow->setFrame(Rect(0, 0, 600, 800));
3280 spyWindow->setTrustedOverlay(true);
3281 spyWindow->setSpy(true);
3282 sp<FakeWindowHandle> window =
3283 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3284 window->setFrame(Rect(0, 0, 600, 800));
3285
3286 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3288
3289 // Send mouse cursor to the window
3290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3291 injectMotionEvent(mDispatcher,
3292 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3293 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003294 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003295 .x(100)
3296 .y(100))
3297 .build()));
3298
3299 // Move mouse cursor
3300 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3301 injectMotionEvent(mDispatcher,
3302 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3303 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003304 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003305 .x(110)
3306 .y(110))
3307 .build()));
3308
3309 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3310 WithSource(AINPUT_SOURCE_MOUSE)));
3311 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3312 WithSource(AINPUT_SOURCE_MOUSE)));
3313 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3314 WithSource(AINPUT_SOURCE_MOUSE)));
3315 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3316 WithSource(AINPUT_SOURCE_MOUSE)));
3317 // Touch down on the window
3318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3319 injectMotionEvent(mDispatcher,
3320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3321 AINPUT_SOURCE_TOUCHSCREEN)
3322 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003323 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003324 .x(200)
3325 .y(200))
3326 .build()));
3327 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3328 WithSource(AINPUT_SOURCE_MOUSE)));
3329 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3330 WithSource(AINPUT_SOURCE_MOUSE)));
3331 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3332 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3333 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3334 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3335
3336 // pilfer the motion, retaining the gesture on the spy window.
3337 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3338 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3339 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3340
3341 // Touch UP on the window
3342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3343 injectMotionEvent(mDispatcher,
3344 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3345 AINPUT_SOURCE_TOUCHSCREEN)
3346 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003347 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003348 .x(200)
3349 .y(200))
3350 .build()));
3351 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3352 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3353
3354 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3355 // to send a new gesture. It should again go to both windows (spy and the window below), just
3356 // like the first gesture did, before pilfering. The window configuration has not changed.
3357
3358 // One more tap - DOWN
3359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3360 injectMotionEvent(mDispatcher,
3361 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3362 AINPUT_SOURCE_TOUCHSCREEN)
3363 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003364 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003365 .x(250)
3366 .y(250))
3367 .build()));
3368 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3369 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3370 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3371 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3372
3373 // Touch UP on the window
3374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3375 injectMotionEvent(mDispatcher,
3376 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3377 AINPUT_SOURCE_TOUCHSCREEN)
3378 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003379 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003380 .x(250)
3381 .y(250))
3382 .build()));
3383 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3384 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3385 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3386 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3387
3388 window->assertNoEvents();
3389 spyWindow->assertNoEvents();
3390}
3391
Garfield Tandf26e862020-07-01 20:18:19 -07003392// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3393// directly in this test.
3394TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003395 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003396 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003397 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003398 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003399
3400 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3401
3402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3403
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003405 injectMotionEvent(mDispatcher,
3406 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3407 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003408 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003409 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003410 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003411 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003413 injectMotionEvent(mDispatcher,
3414 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3415 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003416 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003417 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003418 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3419 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003420
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003422 injectMotionEvent(mDispatcher,
3423 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3424 AINPUT_SOURCE_MOUSE)
3425 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3426 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003427 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003428 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003429 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003430
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003432 injectMotionEvent(mDispatcher,
3433 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3434 AINPUT_SOURCE_MOUSE)
3435 .buttonState(0)
3436 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003437 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003438 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003439 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003440
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003442 injectMotionEvent(mDispatcher,
3443 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3444 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003445 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003446 .build()));
3447 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3448
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003450 injectMotionEvent(mDispatcher,
3451 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3452 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003453 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003454 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003455 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003456}
3457
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003458/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003459 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3460 * is generated.
3461 */
3462TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3464 sp<FakeWindowHandle> window =
3465 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3466 window->setFrame(Rect(0, 0, 1200, 800));
3467
3468 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3469
3470 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3471
3472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3473 injectMotionEvent(mDispatcher,
3474 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3475 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003476 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003477 .x(300)
3478 .y(400))
3479 .build()));
3480 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3481
3482 // Remove the window, but keep the channel.
3483 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3484 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3485}
3486
3487/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003488 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3489 */
3490TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3492 sp<FakeWindowHandle> window =
3493 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3494 window->setFrame(Rect(0, 0, 100, 100));
3495
3496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3497
3498 const int32_t mouseDeviceId = 7;
3499 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003500
3501 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3503 .deviceId(mouseDeviceId)
3504 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3505 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003506 window->consumeMotionEvent(
3507 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3508
3509 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3511 .deviceId(touchDeviceId)
3512 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3513 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003514
3515 window->consumeMotionEvent(
3516 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3517 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3518}
3519
3520/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003521 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003522 * The tap causes a HOVER_EXIT event to be generated because the current event
3523 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003524 */
3525TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3526 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3527 sp<FakeWindowHandle> window =
3528 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3529 window->setFrame(Rect(0, 0, 100, 100));
3530
3531 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3532
3533 // Inject a hover_move from mouse.
3534 NotifyMotionArgs motionArgs =
3535 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3536 ADISPLAY_ID_DEFAULT, {{50, 50}});
3537 motionArgs.xCursorPosition = 50;
3538 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003539 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003540 ASSERT_NO_FATAL_FAILURE(
3541 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3542 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003543
3544 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3547 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003548 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003549 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3550 WithSource(AINPUT_SOURCE_MOUSE))));
3551
3552 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003553 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3554 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3555
Prabir Pradhan678438e2023-04-13 19:32:51 +00003556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3557 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003558 ASSERT_NO_FATAL_FAILURE(
3559 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3560 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3561}
3562
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003563TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3565 sp<FakeWindowHandle> windowDefaultDisplay =
3566 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3567 ADISPLAY_ID_DEFAULT);
3568 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3569 sp<FakeWindowHandle> windowSecondDisplay =
3570 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3571 SECOND_DISPLAY_ID);
3572 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3573
3574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3575 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3576
3577 // Set cursor position in window in default display and check that hover enter and move
3578 // events are generated.
3579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3580 injectMotionEvent(mDispatcher,
3581 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3582 AINPUT_SOURCE_MOUSE)
3583 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003584 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003585 .x(300)
3586 .y(600))
3587 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003588 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003589
3590 // Remove all windows in secondary display and check that no event happens on window in
3591 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003592 mDispatcher->setInputWindows(
3593 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003594 windowDefaultDisplay->assertNoEvents();
3595
3596 // Move cursor position in window in default display and check that only hover move
3597 // event is generated and not hover enter event.
3598 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3599 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3601 injectMotionEvent(mDispatcher,
3602 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3603 AINPUT_SOURCE_MOUSE)
3604 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003605 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003606 .x(400)
3607 .y(700))
3608 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003609 windowDefaultDisplay->consumeMotionEvent(
3610 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3611 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003612 windowDefaultDisplay->assertNoEvents();
3613}
3614
Garfield Tan00f511d2019-06-12 16:55:40 -07003615TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003616 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003617
3618 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003619 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003620 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003621 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003622 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003623 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003624
3625 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3626
Arthur Hung72d8dc32020-03-28 00:48:39 +00003627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003628
3629 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3630 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003632 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003633 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003634 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003635 windowRight->assertNoEvents();
3636}
3637
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003638TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003640 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3641 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003642 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003643
Arthur Hung72d8dc32020-03-28 00:48:39 +00003644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003645 setFocusedWindow(window);
3646
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003647 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003648
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003650
3651 // Window should receive key down event.
3652 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3653
3654 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3655 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003656 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003657 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003658 AKEY_EVENT_FLAG_CANCELED);
3659}
3660
3661TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003662 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003663 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3664 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003665
Arthur Hung72d8dc32020-03-28 00:48:39 +00003666 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003667
Prabir Pradhan678438e2023-04-13 19:32:51 +00003668 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3669 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003670
3671 // Window should receive motion down event.
3672 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3673
3674 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3675 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003676 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003677 window->consumeMotionEvent(
3678 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003679}
3680
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003681TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3684 "Fake Window", ADISPLAY_ID_DEFAULT);
3685
3686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3687
3688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3689 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3690 .build());
3691
3692 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3693
3694 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3695 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3696 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3697
3698 // After the device has been reset, a new hovering stream can be sent to the window
3699 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3700 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3701 .build());
3702 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3703}
3704
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003705TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003707 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3708 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003709 window->setFocusable(true);
3710
3711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3712 setFocusedWindow(window);
3713
3714 window->consumeFocusEvent(true);
3715
Prabir Pradhan678438e2023-04-13 19:32:51 +00003716 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003717 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3718 const nsecs_t injectTime = keyArgs.eventTime;
3719 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003720 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003721 // The dispatching time should be always greater than or equal to intercept key timeout.
3722 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3723 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3724 std::chrono::nanoseconds(interceptKeyTimeout).count());
3725}
3726
3727TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003729 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3730 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003731 window->setFocusable(true);
3732
3733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3734 setFocusedWindow(window);
3735
3736 window->consumeFocusEvent(true);
3737
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003738 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3740 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003741
3742 // Window should receive key event immediately when same key up.
3743 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3744 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3745}
3746
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003747/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003748 * Two windows. First is a regular window. Second does not overlap with the first, and has
3749 * WATCH_OUTSIDE_TOUCH.
3750 * Both windows are owned by the same UID.
3751 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3752 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3753 */
3754TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3756 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3757 "First Window", ADISPLAY_ID_DEFAULT);
3758 window->setFrame(Rect{0, 0, 100, 100});
3759
3760 sp<FakeWindowHandle> outsideWindow =
3761 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3762 ADISPLAY_ID_DEFAULT);
3763 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3764 outsideWindow->setWatchOutsideTouch(true);
3765 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3766 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3767
3768 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3770 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3771 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003772 window->consumeMotionDown();
3773 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3774 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3775 outsideWindow->consumeMotionEvent(
3776 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3777}
3778
3779/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003780 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3781 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3782 * ACTION_OUTSIDE event is sent per gesture.
3783 */
3784TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3785 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003787 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3788 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003789 window->setWatchOutsideTouch(true);
3790 window->setFrame(Rect{0, 0, 100, 100});
3791 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003792 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3793 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003794 secondWindow->setFrame(Rect{100, 100, 200, 200});
3795 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003796 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3797 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003798 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3800
3801 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003802 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3803 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3804 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003805 window->assertNoEvents();
3806 secondWindow->assertNoEvents();
3807
3808 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3809 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003810 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3811 ADISPLAY_ID_DEFAULT,
3812 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003813 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3814 window->consumeMotionEvent(
3815 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003816 secondWindow->consumeMotionDown();
3817 thirdWindow->assertNoEvents();
3818
3819 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3820 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003821 mDispatcher->notifyMotion(
3822 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3823 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003824 window->assertNoEvents();
3825 secondWindow->consumeMotionMove();
3826 thirdWindow->consumeMotionDown();
3827}
3828
Prabir Pradhan814fe082022-07-22 20:22:18 +00003829TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3832 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003833 window->setFocusable(true);
3834
3835 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3836 setFocusedWindow(window);
3837
3838 window->consumeFocusEvent(true);
3839
Prabir Pradhan678438e2023-04-13 19:32:51 +00003840 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3841 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3842 mDispatcher->notifyKey(keyDown);
3843 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003844
3845 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3846 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3847
3848 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3849 mDispatcher->onWindowInfosChanged({}, {});
3850
3851 window->consumeFocusEvent(false);
3852
Prabir Pradhan678438e2023-04-13 19:32:51 +00003853 mDispatcher->notifyKey(keyDown);
3854 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003855 window->assertNoEvents();
3856}
3857
Arthur Hung96483742022-11-15 03:30:48 +00003858TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3859 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3860 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3861 "Fake Window", ADISPLAY_ID_DEFAULT);
3862 // Ensure window is non-split and have some transform.
3863 window->setPreventSplitting(true);
3864 window->setWindowOffset(20, 40);
3865 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3866
3867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3869 {50, 50}))
3870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3871 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3872
3873 const MotionEvent secondFingerDownEvent =
3874 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3875 .displayId(ADISPLAY_ID_DEFAULT)
3876 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003877 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3878 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003879 .build();
3880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3881 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3882 InputEventInjectionSync::WAIT_FOR_RESULT))
3883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3884
3885 const MotionEvent* event = window->consumeMotion();
3886 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3887 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3888 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3889 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3890 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3891}
3892
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003893/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003894 * Ensure the correct coordinate spaces are used by InputDispatcher.
3895 *
3896 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3897 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3898 * space.
3899 */
3900class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3901public:
3902 void SetUp() override {
3903 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003904 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003905 }
3906
3907 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3908 gui::DisplayInfo info;
3909 info.displayId = displayId;
3910 info.transform = transform;
3911 mDisplayInfos.push_back(std::move(info));
3912 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3913 }
3914
3915 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3916 mWindowInfos.push_back(*windowHandle->getInfo());
3917 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3918 }
3919
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003920 void removeAllWindowsAndDisplays() {
3921 mDisplayInfos.clear();
3922 mWindowInfos.clear();
3923 }
3924
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003925 // Set up a test scenario where the display has a scaled projection and there are two windows
3926 // on the display.
3927 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3928 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3929 // respectively.
3930 ui::Transform displayTransform;
3931 displayTransform.set(2, 0, 0, 4);
3932 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3933
3934 std::shared_ptr<FakeApplicationHandle> application =
3935 std::make_shared<FakeApplicationHandle>();
3936
3937 // Add two windows to the display. Their frames are represented in the display space.
3938 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003939 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3940 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003941 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3942 addWindow(firstWindow);
3943
3944 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003945 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3946 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003947 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3948 addWindow(secondWindow);
3949 return {std::move(firstWindow), std::move(secondWindow)};
3950 }
3951
3952private:
3953 std::vector<gui::DisplayInfo> mDisplayInfos;
3954 std::vector<gui::WindowInfo> mWindowInfos;
3955};
3956
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003957TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003958 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3959 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003960 // selected so that if the hit test was performed with the point and the bounds being in
3961 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003962 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3963 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3964 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003965
3966 firstWindow->consumeMotionDown();
3967 secondWindow->assertNoEvents();
3968}
3969
3970// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3971// the event should be treated as being in the logical display space.
3972TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3973 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3974 // Send down to the first window. The point is represented in the logical display space. The
3975 // point is selected so that if the hit test was done in logical display space, then it would
3976 // end up in the incorrect window.
3977 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3978 PointF{75 * 2, 55 * 4});
3979
3980 firstWindow->consumeMotionDown();
3981 secondWindow->assertNoEvents();
3982}
3983
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003984// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3985// event should be treated as being in the logical display space.
3986TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3987 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3988
3989 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3990 ui::Transform injectedEventTransform;
3991 injectedEventTransform.set(matrix);
3992 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3993 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3994
3995 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3996 .displayId(ADISPLAY_ID_DEFAULT)
3997 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003998 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003999 .x(untransformedPoint.x)
4000 .y(untransformedPoint.y))
4001 .build();
4002 event.transform(matrix);
4003
4004 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4005 InputEventInjectionSync::WAIT_FOR_RESULT);
4006
4007 firstWindow->consumeMotionDown();
4008 secondWindow->assertNoEvents();
4009}
4010
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004011TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4012 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4013
4014 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004015 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4016 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4017 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004018
4019 firstWindow->assertNoEvents();
4020 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004021 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004022 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4023
4024 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4025 EXPECT_EQ(300, event->getRawX(0));
4026 EXPECT_EQ(880, event->getRawY(0));
4027
4028 // Ensure that the x and y values are in the window's coordinate space.
4029 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4030 // the logical display space. This will be the origin of the window space.
4031 EXPECT_EQ(100, event->getX(0));
4032 EXPECT_EQ(80, event->getY(0));
4033}
4034
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004035/** Ensure consistent behavior of InputDispatcher in all orientations. */
4036class InputDispatcherDisplayOrientationFixture
4037 : public InputDispatcherDisplayProjectionTest,
4038 public ::testing::WithParamInterface<ui::Rotation> {};
4039
4040// This test verifies the touchable region of a window for all rotations of the display by tapping
4041// in different locations on the display, specifically points close to the four corners of a
4042// window.
4043TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4044 constexpr static int32_t displayWidth = 400;
4045 constexpr static int32_t displayHeight = 800;
4046
4047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4048
4049 const auto rotation = GetParam();
4050
4051 // Set up the display with the specified rotation.
4052 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4053 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4054 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4055 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4056 logicalDisplayWidth, logicalDisplayHeight);
4057 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4058
4059 // Create a window with its bounds determined in the logical display.
4060 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4061 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4062 sp<FakeWindowHandle> window =
4063 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4064 window->setFrame(frameInDisplay, displayTransform);
4065 addWindow(window);
4066
4067 // The following points in logical display space should be inside the window.
4068 static const std::array<vec2, 4> insidePoints{
4069 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4070 for (const auto pointInsideWindow : insidePoints) {
4071 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4072 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4074 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4075 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004076 window->consumeMotionDown();
4077
Prabir Pradhan678438e2023-04-13 19:32:51 +00004078 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4079 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4080 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004081 window->consumeMotionUp();
4082 }
4083
4084 // The following points in logical display space should be outside the window.
4085 static const std::array<vec2, 5> outsidePoints{
4086 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4087 for (const auto pointOutsideWindow : outsidePoints) {
4088 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4089 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004090 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4091 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4092 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004093
Prabir Pradhan678438e2023-04-13 19:32:51 +00004094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4095 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4096 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004097 }
4098 window->assertNoEvents();
4099}
4100
4101// Run the precision tests for all rotations.
4102INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4103 InputDispatcherDisplayOrientationFixture,
4104 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4105 ui::ROTATION_270),
4106 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4107 return ftl::enum_string(testParamInfo.param);
4108 });
4109
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004110using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4111 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004112
4113class TransferTouchFixture : public InputDispatcherTest,
4114 public ::testing::WithParamInterface<TransferFunction> {};
4115
4116TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004117 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004118
4119 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004120 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004121 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4122 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004123 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004124 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004125 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4126 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004127 sp<FakeWindowHandle> wallpaper =
4128 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4129 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004130 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004131 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004132
4133 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004134 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4135 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004136
Svet Ganov5d3bc372020-01-26 23:11:07 -08004137 // Only the first window should get the down event
4138 firstWindow->consumeMotionDown();
4139 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004140 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004141
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004142 // Transfer touch to the second window
4143 TransferFunction f = GetParam();
4144 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4145 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004146 // The first window gets cancel and the second gets down
4147 firstWindow->consumeMotionCancel();
4148 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004149 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004150
4151 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004152 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4153 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004154 // The first window gets no events and the second gets up
4155 firstWindow->assertNoEvents();
4156 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004157 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004158}
4159
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004160/**
4161 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4162 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4163 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4164 * natural to the user.
4165 * In this test, we are sending a pointer to both spy window and first window. We then try to
4166 * transfer touch to the second window. The dispatcher should identify the first window as the
4167 * one that should lose the gesture, and therefore the action should be to move the gesture from
4168 * the first window to the second.
4169 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4170 * the other API, as well.
4171 */
4172TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4174
4175 // Create a couple of windows + a spy window
4176 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004177 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004178 spyWindow->setTrustedOverlay(true);
4179 spyWindow->setSpy(true);
4180 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004181 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004182 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004183 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004184
4185 // Add the windows to the dispatcher
4186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4187
4188 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4190 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004191 // Only the first window and spy should get the down event
4192 spyWindow->consumeMotionDown();
4193 firstWindow->consumeMotionDown();
4194
4195 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4196 // if f === 'transferTouch'.
4197 TransferFunction f = GetParam();
4198 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4199 ASSERT_TRUE(success);
4200 // The first window gets cancel and the second gets down
4201 firstWindow->consumeMotionCancel();
4202 secondWindow->consumeMotionDown();
4203
4204 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004205 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4206 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004207 // The first window gets no events and the second+spy get up
4208 firstWindow->assertNoEvents();
4209 spyWindow->consumeMotionUp();
4210 secondWindow->consumeMotionUp();
4211}
4212
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004213TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004215
4216 PointF touchPoint = {10, 10};
4217
4218 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004219 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004220 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4221 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004222 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004223 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004224 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4225 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004226 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004227
4228 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004230
4231 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004232 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4233 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4234 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004235 // Only the first window should get the down event
4236 firstWindow->consumeMotionDown();
4237 secondWindow->assertNoEvents();
4238
4239 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004240 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4241 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004242 // Only the first window should get the pointer down event
4243 firstWindow->consumeMotionPointerDown(1);
4244 secondWindow->assertNoEvents();
4245
4246 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004247 TransferFunction f = GetParam();
4248 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4249 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004250 // The first window gets cancel and the second gets down and pointer down
4251 firstWindow->consumeMotionCancel();
4252 secondWindow->consumeMotionDown();
4253 secondWindow->consumeMotionPointerDown(1);
4254
4255 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004256 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4257 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004258 // The first window gets nothing and the second gets pointer up
4259 firstWindow->assertNoEvents();
4260 secondWindow->consumeMotionPointerUp(1);
4261
4262 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004263 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4264 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004265 // The first window gets nothing and the second gets up
4266 firstWindow->assertNoEvents();
4267 secondWindow->consumeMotionUp();
4268}
4269
Arthur Hungc539dbb2022-12-08 07:45:36 +00004270TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4271 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4272
4273 // Create a couple of windows
4274 sp<FakeWindowHandle> firstWindow =
4275 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4276 ADISPLAY_ID_DEFAULT);
4277 firstWindow->setDupTouchToWallpaper(true);
4278 sp<FakeWindowHandle> secondWindow =
4279 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4280 ADISPLAY_ID_DEFAULT);
4281 secondWindow->setDupTouchToWallpaper(true);
4282
4283 sp<FakeWindowHandle> wallpaper1 =
4284 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4285 wallpaper1->setIsWallpaper(true);
4286
4287 sp<FakeWindowHandle> wallpaper2 =
4288 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4289 wallpaper2->setIsWallpaper(true);
4290 // Add the windows to the dispatcher
4291 mDispatcher->setInputWindows(
4292 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4293
4294 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4296 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004297
4298 // Only the first window should get the down event
4299 firstWindow->consumeMotionDown();
4300 secondWindow->assertNoEvents();
4301 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4302 wallpaper2->assertNoEvents();
4303
4304 // Transfer touch focus to the second window
4305 TransferFunction f = GetParam();
4306 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4307 ASSERT_TRUE(success);
4308
4309 // The first window gets cancel and the second gets down
4310 firstWindow->consumeMotionCancel();
4311 secondWindow->consumeMotionDown();
4312 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4313 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4314
4315 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004316 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4317 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004318 // The first window gets no events and the second gets up
4319 firstWindow->assertNoEvents();
4320 secondWindow->consumeMotionUp();
4321 wallpaper1->assertNoEvents();
4322 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4323}
4324
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004325// For the cases of single pointer touch and two pointers non-split touch, the api's
4326// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4327// for the case where there are multiple pointers split across several windows.
4328INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4329 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004330 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4331 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004332 return dispatcher->transferTouch(destChannelToken,
4333 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004334 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004335 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4336 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004337 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004338 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004339 }));
4340
Svet Ganov5d3bc372020-01-26 23:11:07 -08004341TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004343
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004344 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004345 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4346 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004347 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004348
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004349 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004350 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4351 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004352 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004353
4354 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004356
4357 PointF pointInFirst = {300, 200};
4358 PointF pointInSecond = {300, 600};
4359
4360 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004361 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4362 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4363 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004364 // Only the first window should get the down event
4365 firstWindow->consumeMotionDown();
4366 secondWindow->assertNoEvents();
4367
4368 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004369 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4370 ADISPLAY_ID_DEFAULT,
4371 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004372 // The first window gets a move and the second a down
4373 firstWindow->consumeMotionMove();
4374 secondWindow->consumeMotionDown();
4375
4376 // Transfer touch focus to the second window
4377 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4378 // The first window gets cancel and the new gets pointer down (it already saw down)
4379 firstWindow->consumeMotionCancel();
4380 secondWindow->consumeMotionPointerDown(1);
4381
4382 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004383 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4384 ADISPLAY_ID_DEFAULT,
4385 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004386 // The first window gets nothing and the second gets pointer up
4387 firstWindow->assertNoEvents();
4388 secondWindow->consumeMotionPointerUp(1);
4389
4390 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004391 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4392 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004393 // The first window gets nothing and the second gets up
4394 firstWindow->assertNoEvents();
4395 secondWindow->consumeMotionUp();
4396}
4397
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004398// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4399// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4400// touch is not supported, so the touch should continue on those windows and the transferred-to
4401// window should get nothing.
4402TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4404
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004405 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004406 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4407 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004408 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004409
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004410 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004411 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4412 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004413 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004414
4415 // Add the windows to the dispatcher
4416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4417
4418 PointF pointInFirst = {300, 200};
4419 PointF pointInSecond = {300, 600};
4420
4421 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004422 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4423 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4424 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004425 // Only the first window should get the down event
4426 firstWindow->consumeMotionDown();
4427 secondWindow->assertNoEvents();
4428
4429 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004430 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4431 ADISPLAY_ID_DEFAULT,
4432 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004433 // The first window gets a move and the second a down
4434 firstWindow->consumeMotionMove();
4435 secondWindow->consumeMotionDown();
4436
4437 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004438 const bool transferred =
4439 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004440 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4441 ASSERT_FALSE(transferred);
4442 firstWindow->assertNoEvents();
4443 secondWindow->assertNoEvents();
4444
4445 // The rest of the dispatch should proceed as normal
4446 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004447 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4448 ADISPLAY_ID_DEFAULT,
4449 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004450 // The first window gets MOVE and the second gets pointer up
4451 firstWindow->consumeMotionMove();
4452 secondWindow->consumeMotionUp();
4453
4454 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004455 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4456 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004457 // The first window gets nothing and the second gets up
4458 firstWindow->consumeMotionUp();
4459 secondWindow->assertNoEvents();
4460}
4461
Arthur Hungabbb9d82021-09-01 14:52:30 +00004462// This case will create two windows and one mirrored window on the default display and mirror
4463// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4464// the windows info of second display before default display.
4465TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4467 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004468 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004469 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004470 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004471 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004472 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004473
4474 sp<FakeWindowHandle> mirrorWindowInPrimary =
4475 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4476 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004477
4478 sp<FakeWindowHandle> firstWindowInSecondary =
4479 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4480 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004481
4482 sp<FakeWindowHandle> secondWindowInSecondary =
4483 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4484 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004485
4486 // Update window info, let it find window handle of second display first.
4487 mDispatcher->setInputWindows(
4488 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4489 {ADISPLAY_ID_DEFAULT,
4490 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4491
4492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4493 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4494 {50, 50}))
4495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4496
4497 // Window should receive motion event.
4498 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4499
4500 // Transfer touch focus
4501 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4502 secondWindowInPrimary->getToken()));
4503 // The first window gets cancel.
4504 firstWindowInPrimary->consumeMotionCancel();
4505 secondWindowInPrimary->consumeMotionDown();
4506
4507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4508 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4509 ADISPLAY_ID_DEFAULT, {150, 50}))
4510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4511 firstWindowInPrimary->assertNoEvents();
4512 secondWindowInPrimary->consumeMotionMove();
4513
4514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4515 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4516 {150, 50}))
4517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4518 firstWindowInPrimary->assertNoEvents();
4519 secondWindowInPrimary->consumeMotionUp();
4520}
4521
4522// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4523// 'transferTouch' api.
4524TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4526 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004527 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004528 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004529 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004530 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004531 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004532
4533 sp<FakeWindowHandle> mirrorWindowInPrimary =
4534 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4535 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004536
4537 sp<FakeWindowHandle> firstWindowInSecondary =
4538 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4539 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004540
4541 sp<FakeWindowHandle> secondWindowInSecondary =
4542 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4543 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004544
4545 // Update window info, let it find window handle of second display first.
4546 mDispatcher->setInputWindows(
4547 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4548 {ADISPLAY_ID_DEFAULT,
4549 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4550
4551 // Touch on second display.
4552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4553 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4555
4556 // Window should receive motion event.
4557 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4558
4559 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004560 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004561
4562 // The first window gets cancel.
4563 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4564 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4565
4566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4567 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4568 SECOND_DISPLAY_ID, {150, 50}))
4569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4570 firstWindowInPrimary->assertNoEvents();
4571 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4572
4573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4574 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4576 firstWindowInPrimary->assertNoEvents();
4577 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4578}
4579
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004580TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004582 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4583 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004584
Vishnu Nair47074b82020-08-14 11:54:47 -07004585 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004587 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004588
4589 window->consumeFocusEvent(true);
4590
Prabir Pradhan678438e2023-04-13 19:32:51 +00004591 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004592
4593 // Window should receive key down event.
4594 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004595
4596 // Should have poked user activity
4597 mFakePolicy->assertUserActivityPoked();
4598}
4599
4600TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4602 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4603 "Fake Window", ADISPLAY_ID_DEFAULT);
4604
4605 window->setDisableUserActivity(true);
4606 window->setFocusable(true);
4607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4608 setFocusedWindow(window);
4609
4610 window->consumeFocusEvent(true);
4611
4612 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4613
4614 // Window should receive key down event.
4615 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4616
4617 // Should have poked user activity
4618 mFakePolicy->assertUserActivityNotPoked();
4619}
4620
4621TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4623 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4624 "Fake Window", ADISPLAY_ID_DEFAULT);
4625
4626 window->setFocusable(true);
4627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4628 setFocusedWindow(window);
4629
4630 window->consumeFocusEvent(true);
4631
4632 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4633 mDispatcher->waitForIdle();
4634
4635 // System key is not passed down
4636 window->assertNoEvents();
4637
4638 // Should have poked user activity
4639 mFakePolicy->assertUserActivityPoked();
4640}
4641
4642TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4645 "Fake Window", ADISPLAY_ID_DEFAULT);
4646
4647 window->setFocusable(true);
4648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4649 setFocusedWindow(window);
4650
4651 window->consumeFocusEvent(true);
4652
4653 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4654 mDispatcher->waitForIdle();
4655
4656 // System key is not passed down
4657 window->assertNoEvents();
4658
4659 // Should have poked user activity
4660 mFakePolicy->assertUserActivityPoked();
4661}
4662
4663TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4666 "Fake Window", ADISPLAY_ID_DEFAULT);
4667
4668 window->setDisableUserActivity(true);
4669 window->setFocusable(true);
4670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4671 setFocusedWindow(window);
4672
4673 window->consumeFocusEvent(true);
4674
4675 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4676 mDispatcher->waitForIdle();
4677
4678 // System key is not passed down
4679 window->assertNoEvents();
4680
4681 // Should have poked user activity
4682 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004683}
4684
4685TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004687 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4688 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004689
Arthur Hung72d8dc32020-03-28 00:48:39 +00004690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004691
Prabir Pradhan678438e2023-04-13 19:32:51 +00004692 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004693 mDispatcher->waitForIdle();
4694
4695 window->assertNoEvents();
4696}
4697
4698// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4699TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004700 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004701 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4702 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004703
Arthur Hung72d8dc32020-03-28 00:48:39 +00004704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004705
4706 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004707 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004708 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004709 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4710 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004711
4712 // Window should receive only the motion event
4713 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4714 window->assertNoEvents(); // Key event or focus event will not be received
4715}
4716
arthurhungea3f4fc2020-12-21 23:18:53 +08004717TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4719
arthurhungea3f4fc2020-12-21 23:18:53 +08004720 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004721 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4722 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004723 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004724
arthurhungea3f4fc2020-12-21 23:18:53 +08004725 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004726 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4727 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004728 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004729
4730 // Add the windows to the dispatcher
4731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4732
4733 PointF pointInFirst = {300, 200};
4734 PointF pointInSecond = {300, 600};
4735
4736 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004737 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4738 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4739 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004740 // Only the first window should get the down event
4741 firstWindow->consumeMotionDown();
4742 secondWindow->assertNoEvents();
4743
4744 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004745 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4746 ADISPLAY_ID_DEFAULT,
4747 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004748 // The first window gets a move and the second a down
4749 firstWindow->consumeMotionMove();
4750 secondWindow->consumeMotionDown();
4751
4752 // Send pointer cancel to the second window
4753 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004754 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004755 {pointInFirst, pointInSecond});
4756 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004757 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004758 // The first window gets move and the second gets cancel.
4759 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4760 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4761
4762 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004763 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4764 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004765 // The first window gets up and the second gets nothing.
4766 firstWindow->consumeMotionUp();
4767 secondWindow->assertNoEvents();
4768}
4769
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004770TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4772
4773 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004774 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004775 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4776 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4777 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4778 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4779
Harry Cutts33476232023-01-30 19:57:29 +00004780 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004781 window->assertNoEvents();
4782 mDispatcher->waitForIdle();
4783}
4784
chaviwd1c23182019-12-20 18:44:56 -08004785class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004786public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004787 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004788 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004789 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004790 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004791 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004792 }
4793
chaviwd1c23182019-12-20 18:44:56 -08004794 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4795
4796 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004797 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4798 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004799 }
4800
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004801 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4802
4803 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4804
chaviwd1c23182019-12-20 18:44:56 -08004805 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004806 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004807 expectedDisplayId, expectedFlags);
4808 }
4809
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004810 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004811 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004812 expectedDisplayId, expectedFlags);
4813 }
4814
chaviwd1c23182019-12-20 18:44:56 -08004815 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004816 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004817 expectedDisplayId, expectedFlags);
4818 }
4819
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004820 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004821 mInputReceiver->consumeMotionEvent(
4822 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4823 WithDisplayId(expectedDisplayId),
4824 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004825 }
4826
Arthur Hungfbfa5722021-11-16 02:45:54 +00004827 void consumeMotionPointerDown(int32_t pointerIdx) {
4828 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4829 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004830 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004831 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004832 }
4833
Evan Rosky84f07f02021-04-16 10:42:42 -07004834 MotionEvent* consumeMotion() {
4835 InputEvent* event = mInputReceiver->consume();
4836 if (!event) {
4837 ADD_FAILURE() << "No event was produced";
4838 return nullptr;
4839 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004840 if (event->getType() != InputEventType::MOTION) {
4841 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004842 return nullptr;
4843 }
4844 return static_cast<MotionEvent*>(event);
4845 }
4846
chaviwd1c23182019-12-20 18:44:56 -08004847 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4848
4849private:
4850 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004851};
4852
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004853using InputDispatcherMonitorTest = InputDispatcherTest;
4854
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004855/**
4856 * Two entities that receive touch: A window, and a global monitor.
4857 * The touch goes to the window, and then the window disappears.
4858 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4859 * for the monitor, as well.
4860 * 1. foregroundWindow
4861 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4862 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004863TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4865 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004866 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004867
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004868 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004869
4870 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4872 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4873 {100, 200}))
4874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4875
4876 // Both the foreground window and the global monitor should receive the touch down
4877 window->consumeMotionDown();
4878 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4879
4880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4881 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4882 ADISPLAY_ID_DEFAULT, {110, 200}))
4883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4884
4885 window->consumeMotionMove();
4886 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4887
4888 // Now the foreground window goes away
4889 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4890 window->consumeMotionCancel();
4891 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4892
4893 // If more events come in, there will be no more foreground window to send them to. This will
4894 // cause a cancel for the monitor, as well.
4895 ASSERT_EQ(InputEventInjectionResult::FAILED,
4896 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4897 ADISPLAY_ID_DEFAULT, {120, 200}))
4898 << "Injection should fail because the window was removed";
4899 window->assertNoEvents();
4900 // Global monitor now gets the cancel
4901 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4902}
4903
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004904TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004906 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4907 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004908 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004909
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004910 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004911
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004913 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004915 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004916 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004917}
4918
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004919TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4920 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004921
Chris Yea209fde2020-07-22 13:54:51 -07004922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004923 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4924 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004925 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004926
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004928 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004930 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004931 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004932
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004933 // Pilfer pointers from the monitor.
4934 // This should not do anything and the window should continue to receive events.
4935 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004936
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004938 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4939 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004941
4942 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4943 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004944}
4945
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004946TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4949 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4951 window->setWindowOffset(20, 40);
4952 window->setWindowTransform(0, 1, -1, 0);
4953
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004954 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004955
4956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4957 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4959 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4960 MotionEvent* event = monitor.consumeMotion();
4961 // Even though window has transform, gesture monitor must not.
4962 ASSERT_EQ(ui::Transform(), event->getTransform());
4963}
4964
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004965TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004966 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004967 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004968
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004969 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004970 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004971 << "Injection should fail if there is a monitor, but no touchable window";
4972 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004973}
4974
chaviw81e2bb92019-12-18 15:03:51 -08004975TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004977 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4978 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004979
Arthur Hung72d8dc32020-03-28 00:48:39 +00004980 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004981
4982 NotifyMotionArgs motionArgs =
4983 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4984 ADISPLAY_ID_DEFAULT);
4985
Prabir Pradhan678438e2023-04-13 19:32:51 +00004986 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08004987 // Window should receive motion down event.
4988 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4989
4990 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004991 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004992 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4993 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4994 motionArgs.pointerCoords[0].getX() - 10);
4995
Prabir Pradhan678438e2023-04-13 19:32:51 +00004996 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004997 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004998 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004999}
5000
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005001/**
5002 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5003 * the device default right away. In the test scenario, we check both the default value,
5004 * and the action of enabling / disabling.
5005 */
5006TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005008 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5009 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005010 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005011
5012 // Set focused application.
5013 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005014 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005015
5016 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005018 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005019 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005020
5021 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005022 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005024 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005025
5026 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005027 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005028 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005029 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005030 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005031 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005032 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005033 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005034
5035 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005036 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005038 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005039
5040 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005041 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005042 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005043 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005044 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005046 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005047 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005048
5049 window->assertNoEvents();
5050}
5051
Gang Wange9087892020-01-07 12:17:14 -05005052TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005053 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005054 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5055 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005056
5057 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005058 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005059
Arthur Hung72d8dc32020-03-28 00:48:39 +00005060 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005061 setFocusedWindow(window);
5062
Harry Cutts33476232023-01-30 19:57:29 +00005063 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005064
Prabir Pradhan678438e2023-04-13 19:32:51 +00005065 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5066 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005067
5068 InputEvent* event = window->consume();
5069 ASSERT_NE(event, nullptr);
5070
5071 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5072 ASSERT_NE(verified, nullptr);
5073 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5074
5075 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5076 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5077 ASSERT_EQ(keyArgs.source, verified->source);
5078 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5079
5080 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5081
5082 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005083 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005084 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005085 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5086 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5087 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5088 ASSERT_EQ(0, verifiedKey.repeatCount);
5089}
5090
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005091TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005093 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5094 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005095
5096 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5097
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005098 ui::Transform transform;
5099 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5100
5101 gui::DisplayInfo displayInfo;
5102 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5103 displayInfo.transform = transform;
5104
5105 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005106
Prabir Pradhan678438e2023-04-13 19:32:51 +00005107 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005108 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5109 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005110 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005111
5112 InputEvent* event = window->consume();
5113 ASSERT_NE(event, nullptr);
5114
5115 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5116 ASSERT_NE(verified, nullptr);
5117 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5118
5119 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5120 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5121 EXPECT_EQ(motionArgs.source, verified->source);
5122 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5123
5124 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5125
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005126 const vec2 rawXY =
5127 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5128 motionArgs.pointerCoords[0].getXYValue());
5129 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5130 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005131 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005132 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005133 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005134 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5135 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5136}
5137
chaviw09c8d2d2020-08-24 15:48:26 -07005138/**
5139 * Ensure that separate calls to sign the same data are generating the same key.
5140 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5141 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5142 * tests.
5143 */
5144TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5145 KeyEvent event = getTestKeyEvent();
5146 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5147
5148 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5149 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5150 ASSERT_EQ(hmac1, hmac2);
5151}
5152
5153/**
5154 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5155 */
5156TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5157 KeyEvent event = getTestKeyEvent();
5158 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5159 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5160
5161 verifiedEvent.deviceId += 1;
5162 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5163
5164 verifiedEvent.source += 1;
5165 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5166
5167 verifiedEvent.eventTimeNanos += 1;
5168 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5169
5170 verifiedEvent.displayId += 1;
5171 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5172
5173 verifiedEvent.action += 1;
5174 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5175
5176 verifiedEvent.downTimeNanos += 1;
5177 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5178
5179 verifiedEvent.flags += 1;
5180 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5181
5182 verifiedEvent.keyCode += 1;
5183 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5184
5185 verifiedEvent.scanCode += 1;
5186 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5187
5188 verifiedEvent.metaState += 1;
5189 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5190
5191 verifiedEvent.repeatCount += 1;
5192 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5193}
5194
Vishnu Nair958da932020-08-21 17:12:37 -07005195TEST_F(InputDispatcherTest, SetFocusedWindow) {
5196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5197 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005198 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005199 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005200 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5202
5203 // Top window is also focusable but is not granted focus.
5204 windowTop->setFocusable(true);
5205 windowSecond->setFocusable(true);
5206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5207 setFocusedWindow(windowSecond);
5208
5209 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5211 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005212
5213 // Focused window should receive event.
5214 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5215 windowTop->assertNoEvents();
5216}
5217
5218TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5220 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005221 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005222 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5223
5224 window->setFocusable(true);
5225 // Release channel for window is no longer valid.
5226 window->releaseChannel();
5227 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5228 setFocusedWindow(window);
5229
5230 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005231 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5232 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005233
5234 // window channel is invalid, so it should not receive any input event.
5235 window->assertNoEvents();
5236}
5237
5238TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5239 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5240 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005241 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005242 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005243 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5244
Vishnu Nair958da932020-08-21 17:12:37 -07005245 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5246 setFocusedWindow(window);
5247
5248 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005249 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5250 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005251
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005252 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005253 window->assertNoEvents();
5254}
5255
5256TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5258 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005259 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005260 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005261 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005262 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5263
5264 windowTop->setFocusable(true);
5265 windowSecond->setFocusable(true);
5266 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5267 setFocusedWindow(windowTop);
5268 windowTop->consumeFocusEvent(true);
5269
Chavi Weingarten847e8512023-03-29 00:26:09 +00005270 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5271 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005272 windowSecond->consumeFocusEvent(true);
5273 windowTop->consumeFocusEvent(false);
5274
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5276 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005277
5278 // Focused window should receive event.
5279 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5280}
5281
Chavi Weingarten847e8512023-03-29 00:26:09 +00005282TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5284 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005285 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005286 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005287 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005288 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5289
5290 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005291 windowSecond->setFocusable(false);
5292 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005294 setFocusedWindow(windowTop);
5295 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005296
Chavi Weingarten847e8512023-03-29 00:26:09 +00005297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5298 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005299
5300 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005301 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005302 windowSecond->assertNoEvents();
5303}
5304
5305TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5307 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005308 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005309 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005310 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5311 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005312 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5313
5314 window->setFocusable(true);
5315 previousFocusedWindow->setFocusable(true);
5316 window->setVisible(false);
5317 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5318 setFocusedWindow(previousFocusedWindow);
5319 previousFocusedWindow->consumeFocusEvent(true);
5320
5321 // Requesting focus on invisible window takes focus from currently focused window.
5322 setFocusedWindow(window);
5323 previousFocusedWindow->consumeFocusEvent(false);
5324
5325 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005327 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5328 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005329
5330 // Window does not get focus event or key down.
5331 window->assertNoEvents();
5332
5333 // Window becomes visible.
5334 window->setVisible(true);
5335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5336
5337 // Window receives focus event.
5338 window->consumeFocusEvent(true);
5339 // Focused window receives key down.
5340 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5341}
5342
Vishnu Nair599f1412021-06-21 10:39:58 -07005343TEST_F(InputDispatcherTest, DisplayRemoved) {
5344 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5345 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005346 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005347 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5348
5349 // window is granted focus.
5350 window->setFocusable(true);
5351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5352 setFocusedWindow(window);
5353 window->consumeFocusEvent(true);
5354
5355 // When a display is removed window loses focus.
5356 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5357 window->consumeFocusEvent(false);
5358}
5359
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005360/**
5361 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5362 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5363 * of the 'slipperyEnterWindow'.
5364 *
5365 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5366 * a way so that the touched location is no longer covered by the top window.
5367 *
5368 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5369 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5370 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5371 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5372 * with ACTION_DOWN).
5373 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5374 * window moved itself away from the touched location and had Flag::SLIPPERY.
5375 *
5376 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5377 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5378 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5379 *
5380 * In this test, we ensure that the event received by the bottom window has
5381 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5382 */
5383TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005384 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5385 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005386
5387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5388 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5389
5390 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005391 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005392 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005393 // Make sure this one overlaps the bottom window
5394 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5395 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5396 // one. Windows with the same owner are not considered to be occluding each other.
5397 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5398
5399 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005400 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005401 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5402
5403 mDispatcher->setInputWindows(
5404 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5405
5406 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5408 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5409 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005410 slipperyExitWindow->consumeMotionDown();
5411 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5412 mDispatcher->setInputWindows(
5413 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5414
Prabir Pradhan678438e2023-04-13 19:32:51 +00005415 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5416 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5417 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005418
5419 slipperyExitWindow->consumeMotionCancel();
5420
5421 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5422 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5423}
5424
Garfield Tan1c7bc862020-01-28 13:24:04 -08005425class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5426protected:
5427 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5428 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5429
Chris Yea209fde2020-07-22 13:54:51 -07005430 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005431 sp<FakeWindowHandle> mWindow;
5432
5433 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005434 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005435 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005436 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005437 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005438 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5439 ASSERT_EQ(OK, mDispatcher->start());
5440
5441 setUpWindow();
5442 }
5443
5444 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005445 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005446 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005447
Vishnu Nair47074b82020-08-14 11:54:47 -07005448 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005450 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005451 mWindow->consumeFocusEvent(true);
5452 }
5453
Chris Ye2ad95392020-09-01 13:44:44 -07005454 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005455 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005456 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005457 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005458 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005459
5460 // Window should receive key down event.
5461 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5462 }
5463
5464 void expectKeyRepeatOnce(int32_t repeatCount) {
5465 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5466 InputEvent* repeatEvent = mWindow->consume();
5467 ASSERT_NE(nullptr, repeatEvent);
5468
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005469 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005470
5471 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5472 uint32_t eventAction = repeatKeyEvent->getAction();
5473 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5474 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5475 }
5476
Chris Ye2ad95392020-09-01 13:44:44 -07005477 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005478 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005479 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005480 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005481 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005482
5483 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005484 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005485 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005486 }
5487};
5488
5489TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005490 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005491 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5492 expectKeyRepeatOnce(repeatCount);
5493 }
5494}
5495
5496TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005497 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005498 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5499 expectKeyRepeatOnce(repeatCount);
5500 }
Harry Cutts33476232023-01-30 19:57:29 +00005501 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005502 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005503 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5504 expectKeyRepeatOnce(repeatCount);
5505 }
5506}
5507
5508TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005509 sendAndConsumeKeyDown(/*deviceId=*/1);
5510 expectKeyRepeatOnce(/*repeatCount=*/1);
5511 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005512 mWindow->assertNoEvents();
5513}
5514
5515TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005516 sendAndConsumeKeyDown(/*deviceId=*/1);
5517 expectKeyRepeatOnce(/*repeatCount=*/1);
5518 sendAndConsumeKeyDown(/*deviceId=*/2);
5519 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005520 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005521 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005522 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005523 expectKeyRepeatOnce(/*repeatCount=*/2);
5524 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005525 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005526 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005527 mWindow->assertNoEvents();
5528}
5529
5530TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005531 sendAndConsumeKeyDown(/*deviceId=*/1);
5532 expectKeyRepeatOnce(/*repeatCount=*/1);
5533 sendAndConsumeKeyDown(/*deviceId=*/2);
5534 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005535 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005536 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005537 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005538 mWindow->assertNoEvents();
5539}
5540
liushenxiang42232912021-05-21 20:24:09 +08005541TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5542 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005543 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005544 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005545 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5546 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5547 mWindow->assertNoEvents();
5548}
5549
Garfield Tan1c7bc862020-01-28 13:24:04 -08005550TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005551 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005552 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005553 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5554 InputEvent* repeatEvent = mWindow->consume();
5555 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5556 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5557 IdGenerator::getSource(repeatEvent->getId()));
5558 }
5559}
5560
5561TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005562 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005563 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005564
5565 std::unordered_set<int32_t> idSet;
5566 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5567 InputEvent* repeatEvent = mWindow->consume();
5568 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5569 int32_t id = repeatEvent->getId();
5570 EXPECT_EQ(idSet.end(), idSet.find(id));
5571 idSet.insert(id);
5572 }
5573}
5574
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005575/* Test InputDispatcher for MultiDisplay */
5576class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5577public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005578 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005579 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005580
Chris Yea209fde2020-07-22 13:54:51 -07005581 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005582 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005583 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005584
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005585 // Set focus window for primary display, but focused display would be second one.
5586 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005587 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005588 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005589 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005590 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005591
Chris Yea209fde2020-07-22 13:54:51 -07005592 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005593 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005594 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005595 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005596 // Set focus display to second one.
5597 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5598 // Set focus window for second display.
5599 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005600 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005601 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005602 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005603 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005604 }
5605
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005606 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005607 InputDispatcherTest::TearDown();
5608
Chris Yea209fde2020-07-22 13:54:51 -07005609 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005610 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005611 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005612 windowInSecondary.clear();
5613 }
5614
5615protected:
Chris Yea209fde2020-07-22 13:54:51 -07005616 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005617 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005618 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005619 sp<FakeWindowHandle> windowInSecondary;
5620};
5621
5622TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5623 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5625 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5626 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005627 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005628 windowInSecondary->assertNoEvents();
5629
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005630 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5632 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005634 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005635 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005636}
5637
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005638TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005639 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5641 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005643 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005644 windowInSecondary->assertNoEvents();
5645
5646 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005648 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005649 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005650 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005651
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005652 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005653 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005654
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005655 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005656 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005657 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005658
5659 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005660 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005661 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005662 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005663 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005664 windowInSecondary->assertNoEvents();
5665}
5666
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005667// Test per-display input monitors for motion event.
5668TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005669 FakeMonitorReceiver monitorInPrimary =
5670 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5671 FakeMonitorReceiver monitorInSecondary =
5672 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005673
5674 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5676 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005678 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005679 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005680 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005681 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005682
5683 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5685 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005687 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005688 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005689 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005690 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005691
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005692 // Lift up the touch from the second display
5693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5694 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5696 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5697 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5698
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005699 // Test inject a non-pointer motion event.
5700 // If specific a display, it will dispatch to the focused window of particular display,
5701 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5703 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005705 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005706 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005707 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005708 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005709}
5710
5711// Test per-display input monitors for key event.
5712TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005713 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005714 FakeMonitorReceiver monitorInPrimary =
5715 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5716 FakeMonitorReceiver monitorInSecondary =
5717 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005718
5719 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5721 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005722 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005723 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005724 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005725 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005726}
5727
Vishnu Nair958da932020-08-21 17:12:37 -07005728TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5729 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005730 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005731 secondWindowInPrimary->setFocusable(true);
5732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5733 setFocusedWindow(secondWindowInPrimary);
5734 windowInPrimary->consumeFocusEvent(false);
5735 secondWindowInPrimary->consumeFocusEvent(true);
5736
5737 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5739 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005740 windowInPrimary->assertNoEvents();
5741 windowInSecondary->assertNoEvents();
5742 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5743}
5744
Arthur Hungdfd528e2021-12-08 13:23:04 +00005745TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5746 FakeMonitorReceiver monitorInPrimary =
5747 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5748 FakeMonitorReceiver monitorInSecondary =
5749 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5750
5751 // Test touch down on primary display.
5752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5753 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5755 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5756 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5757
5758 // Test touch down on second display.
5759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5760 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5762 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5763 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5764
5765 // Trigger cancel touch.
5766 mDispatcher->cancelCurrentTouch();
5767 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5768 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5769 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5770 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5771
5772 // Test inject a move motion event, no window/monitor should receive the event.
5773 ASSERT_EQ(InputEventInjectionResult::FAILED,
5774 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5775 ADISPLAY_ID_DEFAULT, {110, 200}))
5776 << "Inject motion event should return InputEventInjectionResult::FAILED";
5777 windowInPrimary->assertNoEvents();
5778 monitorInPrimary.assertNoEvents();
5779
5780 ASSERT_EQ(InputEventInjectionResult::FAILED,
5781 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5782 SECOND_DISPLAY_ID, {110, 200}))
5783 << "Inject motion event should return InputEventInjectionResult::FAILED";
5784 windowInSecondary->assertNoEvents();
5785 monitorInSecondary.assertNoEvents();
5786}
5787
Jackal Guof9696682018-10-05 12:23:23 +08005788class InputFilterTest : public InputDispatcherTest {
5789protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005790 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5791 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005792 NotifyMotionArgs motionArgs;
5793
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005794 motionArgs =
5795 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005796 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005797 motionArgs =
5798 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005799 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005800 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005801 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005802 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5803 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005804 } else {
5805 mFakePolicy->assertFilterInputEventWasNotCalled();
5806 }
5807 }
5808
5809 void testNotifyKey(bool expectToBeFiltered) {
5810 NotifyKeyArgs keyArgs;
5811
5812 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005813 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005814 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005815 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005816 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005817
5818 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005819 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005820 } else {
5821 mFakePolicy->assertFilterInputEventWasNotCalled();
5822 }
5823 }
5824};
5825
5826// Test InputFilter for MotionEvent
5827TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5828 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5829 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5830 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5831
5832 // Enable InputFilter
5833 mDispatcher->setInputFilterEnabled(true);
5834 // Test touch on both primary and second display, and check if both events are filtered.
5835 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5836 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5837
5838 // Disable InputFilter
5839 mDispatcher->setInputFilterEnabled(false);
5840 // Test touch on both primary and second display, and check if both events aren't filtered.
5841 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5842 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5843}
5844
5845// Test InputFilter for KeyEvent
5846TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5847 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5848 testNotifyKey(/*expectToBeFiltered*/ false);
5849
5850 // Enable InputFilter
5851 mDispatcher->setInputFilterEnabled(true);
5852 // Send a key event, and check if it is filtered.
5853 testNotifyKey(/*expectToBeFiltered*/ true);
5854
5855 // Disable InputFilter
5856 mDispatcher->setInputFilterEnabled(false);
5857 // Send a key event, and check if it isn't filtered.
5858 testNotifyKey(/*expectToBeFiltered*/ false);
5859}
5860
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005861// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5862// logical display coordinate space.
5863TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5864 ui::Transform firstDisplayTransform;
5865 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5866 ui::Transform secondDisplayTransform;
5867 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5868
5869 std::vector<gui::DisplayInfo> displayInfos(2);
5870 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5871 displayInfos[0].transform = firstDisplayTransform;
5872 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5873 displayInfos[1].transform = secondDisplayTransform;
5874
5875 mDispatcher->onWindowInfosChanged({}, displayInfos);
5876
5877 // Enable InputFilter
5878 mDispatcher->setInputFilterEnabled(true);
5879
5880 // Ensure the correct transforms are used for the displays.
5881 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5882 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5883}
5884
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005885class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5886protected:
5887 virtual void SetUp() override {
5888 InputDispatcherTest::SetUp();
5889
5890 /**
5891 * We don't need to enable input filter to test the injected event policy, but we enabled it
5892 * here to make the tests more realistic, since this policy only matters when inputfilter is
5893 * on.
5894 */
5895 mDispatcher->setInputFilterEnabled(true);
5896
5897 std::shared_ptr<InputApplicationHandle> application =
5898 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005899 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5900 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005901
5902 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5903 mWindow->setFocusable(true);
5904 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5905 setFocusedWindow(mWindow);
5906 mWindow->consumeFocusEvent(true);
5907 }
5908
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005909 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5910 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005911 KeyEvent event;
5912
5913 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5914 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5915 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005916 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005917 const int32_t additionalPolicyFlags =
5918 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005920 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005921 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5922 policyFlags | additionalPolicyFlags));
5923
5924 InputEvent* received = mWindow->consume();
5925 ASSERT_NE(nullptr, received);
5926 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005927 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005928 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5929 ASSERT_EQ(flags, keyEvent.getFlags());
5930 }
5931
5932 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5933 int32_t flags) {
5934 MotionEvent event;
5935 PointerProperties pointerProperties[1];
5936 PointerCoords pointerCoords[1];
5937 pointerProperties[0].clear();
5938 pointerProperties[0].id = 0;
5939 pointerCoords[0].clear();
5940 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5941 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5942
5943 ui::Transform identityTransform;
5944 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5945 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5946 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5947 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5948 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005949 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005950 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005951 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5952
5953 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005955 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005956 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5957 policyFlags | additionalPolicyFlags));
5958
5959 InputEvent* received = mWindow->consume();
5960 ASSERT_NE(nullptr, received);
5961 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005962 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005963 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5964 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005965 }
5966
5967private:
5968 sp<FakeWindowHandle> mWindow;
5969};
5970
5971TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005972 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5973 // filter. Without it, the event will no different from a regularly injected event, and the
5974 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005975 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5976 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005977}
5978
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005979TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005980 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005981 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005982 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5983}
5984
5985TEST_F(InputFilterInjectionPolicyTest,
5986 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5987 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005988 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005989 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005990}
5991
5992TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005993 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5994 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005995}
5996
chaviwfd6d3512019-03-25 13:23:49 -07005997class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005998 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005999 InputDispatcherTest::SetUp();
6000
Chris Yea209fde2020-07-22 13:54:51 -07006001 std::shared_ptr<FakeApplicationHandle> application =
6002 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006003 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006004 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006005 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006006
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006007 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006008 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006009 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006010
6011 // Set focused application.
6012 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006013 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006014
6015 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006017 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006018 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006019 }
6020
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006021 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006022 InputDispatcherTest::TearDown();
6023
6024 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006025 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006026 }
6027
6028protected:
6029 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006030 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006031 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006032};
6033
6034// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6035// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6036// the onPointerDownOutsideFocus callback.
6037TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006039 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6040 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006042 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006043
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006044 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006045 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6046}
6047
6048// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6049// DOWN on the window that doesn't have focus. Ensure no window received the
6050// onPointerDownOutsideFocus callback.
6051TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006053 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006055 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006056
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006057 ASSERT_TRUE(mDispatcher->waitForIdle());
6058 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006059}
6060
6061// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6062// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6063TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6065 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006066 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006067 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006068
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006069 ASSERT_TRUE(mDispatcher->waitForIdle());
6070 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006071}
6072
6073// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6074// DOWN on the window that already has focus. Ensure no window received the
6075// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006076TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006078 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006079 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006081 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006082
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006083 ASSERT_TRUE(mDispatcher->waitForIdle());
6084 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006085}
6086
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006087// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6088// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6089TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6090 const MotionEvent event =
6091 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6092 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006093 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006094 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6095 .build();
6096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6098 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6099
6100 ASSERT_TRUE(mDispatcher->waitForIdle());
6101 mFakePolicy->assertOnPointerDownWasNotCalled();
6102 // Ensure that the unfocused window did not receive any FOCUS events.
6103 mUnfocusedWindow->assertNoEvents();
6104}
6105
chaviwaf87b3e2019-10-01 16:59:28 -07006106// These tests ensures we can send touch events to a single client when there are multiple input
6107// windows that point to the same client token.
6108class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6109 virtual void SetUp() override {
6110 InputDispatcherTest::SetUp();
6111
Chris Yea209fde2020-07-22 13:54:51 -07006112 std::shared_ptr<FakeApplicationHandle> application =
6113 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006114 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6115 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006116 mWindow1->setFrame(Rect(0, 0, 100, 100));
6117
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006118 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6119 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006120 mWindow2->setFrame(Rect(100, 100, 200, 200));
6121
Arthur Hung72d8dc32020-03-28 00:48:39 +00006122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006123 }
6124
6125protected:
6126 sp<FakeWindowHandle> mWindow1;
6127 sp<FakeWindowHandle> mWindow2;
6128
6129 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006130 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006131 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6132 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006133 }
6134
6135 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6136 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006137 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006138 InputEvent* event = window->consume();
6139
6140 ASSERT_NE(nullptr, event) << name.c_str()
6141 << ": consumer should have returned non-NULL event.";
6142
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006143 ASSERT_EQ(InputEventType::MOTION, event->getType())
6144 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006145
6146 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006147 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006148 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006149
6150 for (size_t i = 0; i < points.size(); i++) {
6151 float expectedX = points[i].x;
6152 float expectedY = points[i].y;
6153
6154 EXPECT_EQ(expectedX, motionEvent.getX(i))
6155 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6156 << ", got " << motionEvent.getX(i);
6157 EXPECT_EQ(expectedY, motionEvent.getY(i))
6158 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6159 << ", got " << motionEvent.getY(i);
6160 }
6161 }
chaviw9eaa22c2020-07-01 16:21:27 -07006162
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006163 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006164 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006165 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6166 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006167
6168 // Always consume from window1 since it's the window that has the InputReceiver
6169 consumeMotionEvent(mWindow1, action, expectedPoints);
6170 }
chaviwaf87b3e2019-10-01 16:59:28 -07006171};
6172
6173TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6174 // Touch Window 1
6175 PointF touchedPoint = {10, 10};
6176 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006177 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006178
6179 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006180 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006181
6182 // Touch Window 2
6183 touchedPoint = {150, 150};
6184 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006185 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006186}
6187
chaviw9eaa22c2020-07-01 16:21:27 -07006188TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6189 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006190 mWindow2->setWindowScale(0.5f, 0.5f);
6191
6192 // Touch Window 1
6193 PointF touchedPoint = {10, 10};
6194 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006195 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006196 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006197 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006198
6199 // Touch Window 2
6200 touchedPoint = {150, 150};
6201 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006202 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6203 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006204
chaviw9eaa22c2020-07-01 16:21:27 -07006205 // Update the transform so rotation is set
6206 mWindow2->setWindowTransform(0, -1, 1, 0);
6207 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6208 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006209}
6210
chaviw9eaa22c2020-07-01 16:21:27 -07006211TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006212 mWindow2->setWindowScale(0.5f, 0.5f);
6213
6214 // Touch Window 1
6215 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6216 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006217 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006218
6219 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006220 touchedPoints.push_back(PointF{150, 150});
6221 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006222 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006223
chaviw9eaa22c2020-07-01 16:21:27 -07006224 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006225 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006226 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006227
chaviw9eaa22c2020-07-01 16:21:27 -07006228 // Update the transform so rotation is set for Window 2
6229 mWindow2->setWindowTransform(0, -1, 1, 0);
6230 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006231 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006232}
6233
chaviw9eaa22c2020-07-01 16:21:27 -07006234TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006235 mWindow2->setWindowScale(0.5f, 0.5f);
6236
6237 // Touch Window 1
6238 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6239 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006240 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006241
6242 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006243 touchedPoints.push_back(PointF{150, 150});
6244 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006245
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006246 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006247
6248 // Move both windows
6249 touchedPoints = {{20, 20}, {175, 175}};
6250 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6251 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6252
chaviw9eaa22c2020-07-01 16:21:27 -07006253 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006254
chaviw9eaa22c2020-07-01 16:21:27 -07006255 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006256 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006257 expectedPoints.pop_back();
6258
6259 // Touch Window 2
6260 mWindow2->setWindowTransform(0, -1, 1, 0);
6261 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006262 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006263
6264 // Move both windows
6265 touchedPoints = {{20, 20}, {175, 175}};
6266 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6267 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6268
6269 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006270}
6271
6272TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6273 mWindow1->setWindowScale(0.5f, 0.5f);
6274
6275 // Touch Window 1
6276 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6277 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006278 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006279
6280 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006281 touchedPoints.push_back(PointF{150, 150});
6282 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006283
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006284 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006285
6286 // Move both windows
6287 touchedPoints = {{20, 20}, {175, 175}};
6288 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6289 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6290
chaviw9eaa22c2020-07-01 16:21:27 -07006291 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006292}
6293
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006294/**
6295 * When one of the windows is slippery, the touch should not slip into the other window with the
6296 * same input channel.
6297 */
6298TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6299 mWindow1->setSlippery(true);
6300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6301
6302 // Touch down in window 1
6303 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6304 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6305 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6306
6307 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6308 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6309 // getting generated.
6310 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6311 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6312
6313 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6314}
6315
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006316class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6317 virtual void SetUp() override {
6318 InputDispatcherTest::SetUp();
6319
Chris Yea209fde2020-07-22 13:54:51 -07006320 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006321 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006322 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6323 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006324 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006325 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006326 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006327
6328 // Set focused application.
6329 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6330
6331 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006332 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006333 mWindow->consumeFocusEvent(true);
6334 }
6335
6336 virtual void TearDown() override {
6337 InputDispatcherTest::TearDown();
6338 mWindow.clear();
6339 }
6340
6341protected:
Chris Yea209fde2020-07-22 13:54:51 -07006342 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006343 sp<FakeWindowHandle> mWindow;
6344 static constexpr PointF WINDOW_LOCATION = {20, 20};
6345
6346 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006348 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6349 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006351 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6352 WINDOW_LOCATION));
6353 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006354
6355 sp<FakeWindowHandle> addSpyWindow() {
6356 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006357 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006358 spy->setTrustedOverlay(true);
6359 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006360 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006361 spy->setDispatchingTimeout(30ms);
6362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6363 return spy;
6364 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006365};
6366
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006367// Send a tap and respond, which should not cause an ANR.
6368TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6369 tapOnWindow();
6370 mWindow->consumeMotionDown();
6371 mWindow->consumeMotionUp();
6372 ASSERT_TRUE(mDispatcher->waitForIdle());
6373 mFakePolicy->assertNotifyAnrWasNotCalled();
6374}
6375
6376// Send a regular key and respond, which should not cause an ANR.
6377TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006379 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6380 ASSERT_TRUE(mDispatcher->waitForIdle());
6381 mFakePolicy->assertNotifyAnrWasNotCalled();
6382}
6383
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006384TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6385 mWindow->setFocusable(false);
6386 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6387 mWindow->consumeFocusEvent(false);
6388
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006389 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006390 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6391 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6392 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006394 // Key will not go to window because we have no focused window.
6395 // The 'no focused window' ANR timer should start instead.
6396
6397 // Now, the focused application goes away.
6398 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6399 // The key should get dropped and there should be no ANR.
6400
6401 ASSERT_TRUE(mDispatcher->waitForIdle());
6402 mFakePolicy->assertNotifyAnrWasNotCalled();
6403}
6404
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006405// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006406// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6407// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006408TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006410 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6411 WINDOW_LOCATION));
6412
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006413 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6414 ASSERT_TRUE(sequenceNum);
6415 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006416 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006417
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006418 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006419 mWindow->consumeMotionEvent(
6420 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006421 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006422 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006423}
6424
6425// Send a key to the app and have the app not respond right away.
6426TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6427 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006429 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6430 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006431 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006432 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006433 ASSERT_TRUE(mDispatcher->waitForIdle());
6434}
6435
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006436// We have a focused application, but no focused window
6437TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006438 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006439 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6440 mWindow->consumeFocusEvent(false);
6441
6442 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006444 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6445 WINDOW_LOCATION));
6446 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6447 mDispatcher->waitForIdle();
6448 mFakePolicy->assertNotifyAnrWasNotCalled();
6449
6450 // Once a focused event arrives, we get an ANR for this application
6451 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6452 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006453 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006454 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6455 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006456 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006457 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006458 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006459 ASSERT_TRUE(mDispatcher->waitForIdle());
6460}
6461
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006462/**
6463 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6464 * there will not be an ANR.
6465 */
6466TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6467 mWindow->setFocusable(false);
6468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6469 mWindow->consumeFocusEvent(false);
6470
6471 KeyEvent event;
6472 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6473 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6474
6475 // Define a valid key down event that is stale (too old).
6476 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6477 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006478 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006479
6480 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6481
6482 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006483 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006484 InputEventInjectionSync::WAIT_FOR_RESULT,
6485 INJECT_EVENT_TIMEOUT, policyFlags);
6486 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6487 << "Injection should fail because the event is stale";
6488
6489 ASSERT_TRUE(mDispatcher->waitForIdle());
6490 mFakePolicy->assertNotifyAnrWasNotCalled();
6491 mWindow->assertNoEvents();
6492}
6493
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006494// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006495// Make sure that we don't notify policy twice about the same ANR.
6496TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006497 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6499 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006500
6501 // Once a focused event arrives, we get an ANR for this application
6502 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6503 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006504 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006505 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6506 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006507 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006508 const std::chrono::duration appTimeout =
6509 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6510 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006511
Vishnu Naire4df8752022-09-08 09:17:55 -07006512 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006513 // ANR should not be raised again. It is up to policy to do that if it desires.
6514 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006515
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006516 // If we now get a focused window, the ANR should stop, but the policy handles that via
6517 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006518 ASSERT_TRUE(mDispatcher->waitForIdle());
6519}
6520
6521// We have a focused application, but no focused window
6522TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006523 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6525 mWindow->consumeFocusEvent(false);
6526
6527 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006528 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006529 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006530 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6531 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006532
Vishnu Naire4df8752022-09-08 09:17:55 -07006533 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6534 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006535
6536 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006537 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006538 ASSERT_TRUE(mDispatcher->waitForIdle());
6539 mWindow->assertNoEvents();
6540}
6541
6542/**
6543 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6544 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6545 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6546 * the ANR mechanism should still work.
6547 *
6548 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6549 * DOWN event, while not responding on the second one.
6550 */
6551TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6552 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6553 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6554 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6555 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6556 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006557 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006558
6559 // Now send ACTION_UP, with identical timestamp
6560 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6561 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6562 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6563 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006564 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006565
6566 // We have now sent down and up. Let's consume first event and then ANR on the second.
6567 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6568 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006569 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006570}
6571
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006572// A spy window can receive an ANR
6573TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6574 sp<FakeWindowHandle> spy = addSpyWindow();
6575
6576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6577 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6578 WINDOW_LOCATION));
6579 mWindow->consumeMotionDown();
6580
6581 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6582 ASSERT_TRUE(sequenceNum);
6583 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006584 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006585
6586 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006587 spy->consumeMotionEvent(
6588 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006589 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006590 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006591}
6592
6593// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006594// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006595TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6596 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006597
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6599 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006600 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006602
6603 // Stuck on the ACTION_UP
6604 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006605 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006606
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006607 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006608 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006609 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6610 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006611
6612 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6613 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006614 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006615 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006616 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006617}
6618
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006619// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006620// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006621TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6622 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006623
6624 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006625 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6626 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006627
6628 mWindow->consumeMotionDown();
6629 // Stuck on the ACTION_UP
6630 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006631 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006632
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006633 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006634 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006635 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6636 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006637
6638 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6639 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006640 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006641 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006642 spy->assertNoEvents();
6643}
6644
6645TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6646 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6647
6648 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6649
6650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6651 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6652 WINDOW_LOCATION));
6653
6654 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6655 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6656 ASSERT_TRUE(consumeSeq);
6657
Prabir Pradhanedd96402022-02-15 01:46:16 -08006658 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006659
6660 monitor.finishEvent(*consumeSeq);
6661 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6662
6663 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006664 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006665}
6666
6667// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6668// process events, you don't get an anr. When the window later becomes unresponsive again, you
6669// get an ANR again.
6670// 1. tap -> block on ACTION_UP -> receive ANR
6671// 2. consume all pending events (= queue becomes healthy again)
6672// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6673TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6674 tapOnWindow();
6675
6676 mWindow->consumeMotionDown();
6677 // Block on ACTION_UP
6678 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006679 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006680 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6681 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006682 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006683 mWindow->assertNoEvents();
6684
6685 tapOnWindow();
6686 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006687 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006688 mWindow->consumeMotionUp();
6689
6690 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006691 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006692 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006693 mWindow->assertNoEvents();
6694}
6695
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006696// If a connection remains unresponsive for a while, make sure policy is only notified once about
6697// it.
6698TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006700 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6701 WINDOW_LOCATION));
6702
6703 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006704 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006705 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006706 // 'notifyConnectionUnresponsive' should only be called once per connection
6707 mFakePolicy->assertNotifyAnrWasNotCalled();
6708 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006709 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006710 mWindow->consumeMotionEvent(
6711 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006712 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006713 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006714 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006715 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006716}
6717
6718/**
6719 * If a window is processing a motion event, and then a key event comes in, the key event should
6720 * not to to the focused window until the motion is processed.
6721 *
6722 * Warning!!!
6723 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6724 * and the injection timeout that we specify when injecting the key.
6725 * We must have the injection timeout (10ms) be smaller than
6726 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6727 *
6728 * If that value changes, this test should also change.
6729 */
6730TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6731 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6733
6734 tapOnWindow();
6735 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6736 ASSERT_TRUE(downSequenceNum);
6737 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6738 ASSERT_TRUE(upSequenceNum);
6739 // Don't finish the events yet, and send a key
6740 // Injection will "succeed" because we will eventually give up and send the key to the focused
6741 // window even if motions are still being processed. But because the injection timeout is short,
6742 // we will receive INJECTION_TIMED_OUT as the result.
6743
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006744 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006745 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006746 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6747 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006748 // Key will not be sent to the window, yet, because the window is still processing events
6749 // and the key remains pending, waiting for the touch events to be processed
6750 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6751 ASSERT_FALSE(keySequenceNum);
6752
6753 std::this_thread::sleep_for(500ms);
6754 // if we wait long enough though, dispatcher will give up, and still send the key
6755 // to the focused window, even though we have not yet finished the motion event
6756 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6757 mWindow->finishEvent(*downSequenceNum);
6758 mWindow->finishEvent(*upSequenceNum);
6759}
6760
6761/**
6762 * If a window is processing a motion event, and then a key event comes in, the key event should
6763 * not go to the focused window until the motion is processed.
6764 * If then a new motion comes in, then the pending key event should be going to the currently
6765 * focused window right away.
6766 */
6767TEST_F(InputDispatcherSingleWindowAnr,
6768 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6769 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6771
6772 tapOnWindow();
6773 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6774 ASSERT_TRUE(downSequenceNum);
6775 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6776 ASSERT_TRUE(upSequenceNum);
6777 // Don't finish the events yet, and send a key
6778 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006780 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6781 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006782 // At this point, key is still pending, and should not be sent to the application yet.
6783 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6784 ASSERT_FALSE(keySequenceNum);
6785
6786 // Now tap down again. It should cause the pending key to go to the focused window right away.
6787 tapOnWindow();
6788 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6789 // the other events yet. We can finish events in any order.
6790 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6791 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6792 mWindow->consumeMotionDown();
6793 mWindow->consumeMotionUp();
6794 mWindow->assertNoEvents();
6795}
6796
6797class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6798 virtual void SetUp() override {
6799 InputDispatcherTest::SetUp();
6800
Chris Yea209fde2020-07-22 13:54:51 -07006801 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006802 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006803 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6804 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006805 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006807 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006808
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006809 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6810 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006811 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006812 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813
6814 // Set focused application.
6815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006816 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006817
6818 // Expect one focus window exist in display.
6819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006820 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006821 mFocusedWindow->consumeFocusEvent(true);
6822 }
6823
6824 virtual void TearDown() override {
6825 InputDispatcherTest::TearDown();
6826
6827 mUnfocusedWindow.clear();
6828 mFocusedWindow.clear();
6829 }
6830
6831protected:
Chris Yea209fde2020-07-22 13:54:51 -07006832 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006833 sp<FakeWindowHandle> mUnfocusedWindow;
6834 sp<FakeWindowHandle> mFocusedWindow;
6835 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6836 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6837 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6838
6839 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6840
6841 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6842
6843private:
6844 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006846 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6847 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006849 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6850 location));
6851 }
6852};
6853
6854// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6855// should be ANR'd first.
6856TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006858 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6859 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006861 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006862 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006863 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006864 // We consumed all events, so no ANR
6865 ASSERT_TRUE(mDispatcher->waitForIdle());
6866 mFakePolicy->assertNotifyAnrWasNotCalled();
6867
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006869 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6870 FOCUSED_WINDOW_LOCATION));
6871 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6872 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006873
6874 const std::chrono::duration timeout =
6875 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006876 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006877 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6878 // sequence to make it consistent
6879 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006880 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006881 mFocusedWindow->consumeMotionDown();
6882 // This cancel is generated because the connection was unresponsive
6883 mFocusedWindow->consumeMotionCancel();
6884 mFocusedWindow->assertNoEvents();
6885 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006886 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006887 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6888 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006889 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006890}
6891
6892// If we have 2 windows with identical timeouts that are both unresponsive,
6893// it doesn't matter which order they should have ANR.
6894// But we should receive ANR for both.
6895TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6896 // Set the timeout for unfocused window to match the focused window
6897 mUnfocusedWindow->setDispatchingTimeout(10ms);
6898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6899
6900 tapOnFocusedWindow();
6901 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006902 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6903 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6904 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905
6906 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006907 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6908 mFocusedWindow->getToken() == anrConnectionToken2);
6909 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6910 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911
6912 ASSERT_TRUE(mDispatcher->waitForIdle());
6913 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006914
6915 mFocusedWindow->consumeMotionDown();
6916 mFocusedWindow->consumeMotionUp();
6917 mUnfocusedWindow->consumeMotionOutside();
6918
Prabir Pradhanedd96402022-02-15 01:46:16 -08006919 sp<IBinder> responsiveToken1, responsiveToken2;
6920 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6921 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006922
6923 // Both applications should be marked as responsive, in any order
6924 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6925 mFocusedWindow->getToken() == responsiveToken2);
6926 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6927 mUnfocusedWindow->getToken() == responsiveToken2);
6928 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006929}
6930
6931// If a window is already not responding, the second tap on the same window should be ignored.
6932// We should also log an error to account for the dropped event (not tested here).
6933// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6934TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6935 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006936 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006937 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006938 // Receive the events, but don't respond
6939 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6940 ASSERT_TRUE(downEventSequenceNum);
6941 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6942 ASSERT_TRUE(upEventSequenceNum);
6943 const std::chrono::duration timeout =
6944 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006945 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006946
6947 // Tap once again
6948 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006949 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006950 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6951 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006952 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006953 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6954 FOCUSED_WINDOW_LOCATION));
6955 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6956 // valid touch target
6957 mUnfocusedWindow->assertNoEvents();
6958
6959 // Consume the first tap
6960 mFocusedWindow->finishEvent(*downEventSequenceNum);
6961 mFocusedWindow->finishEvent(*upEventSequenceNum);
6962 ASSERT_TRUE(mDispatcher->waitForIdle());
6963 // The second tap did not go to the focused window
6964 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006965 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006966 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6967 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006968 mFakePolicy->assertNotifyAnrWasNotCalled();
6969}
6970
6971// If you tap outside of all windows, there will not be ANR
6972TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006973 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6975 LOCATION_OUTSIDE_ALL_WINDOWS));
6976 ASSERT_TRUE(mDispatcher->waitForIdle());
6977 mFakePolicy->assertNotifyAnrWasNotCalled();
6978}
6979
6980// Since the focused window is paused, tapping on it should not produce any events
6981TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6982 mFocusedWindow->setPaused(true);
6983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6984
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006985 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006986 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6987 FOCUSED_WINDOW_LOCATION));
6988
6989 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6990 ASSERT_TRUE(mDispatcher->waitForIdle());
6991 // Should not ANR because the window is paused, and touches shouldn't go to it
6992 mFakePolicy->assertNotifyAnrWasNotCalled();
6993
6994 mFocusedWindow->assertNoEvents();
6995 mUnfocusedWindow->assertNoEvents();
6996}
6997
6998/**
6999 * If a window is processing a motion event, and then a key event comes in, the key event should
7000 * not to to the focused window until the motion is processed.
7001 * If a different window becomes focused at this time, the key should go to that window instead.
7002 *
7003 * Warning!!!
7004 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7005 * and the injection timeout that we specify when injecting the key.
7006 * We must have the injection timeout (10ms) be smaller than
7007 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7008 *
7009 * If that value changes, this test should also change.
7010 */
7011TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7012 // Set a long ANR timeout to prevent it from triggering
7013 mFocusedWindow->setDispatchingTimeout(2s);
7014 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7015
7016 tapOnUnfocusedWindow();
7017 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7018 ASSERT_TRUE(downSequenceNum);
7019 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7020 ASSERT_TRUE(upSequenceNum);
7021 // Don't finish the events yet, and send a key
7022 // Injection will succeed because we will eventually give up and send the key to the focused
7023 // window even if motions are still being processed.
7024
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007025 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007026 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7027 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007029 // Key will not be sent to the window, yet, because the window is still processing events
7030 // and the key remains pending, waiting for the touch events to be processed
7031 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7032 ASSERT_FALSE(keySequenceNum);
7033
7034 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007035 mFocusedWindow->setFocusable(false);
7036 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007037 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007038 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007039
7040 // Focus events should precede the key events
7041 mUnfocusedWindow->consumeFocusEvent(true);
7042 mFocusedWindow->consumeFocusEvent(false);
7043
7044 // Finish the tap events, which should unblock dispatcher
7045 mUnfocusedWindow->finishEvent(*downSequenceNum);
7046 mUnfocusedWindow->finishEvent(*upSequenceNum);
7047
7048 // Now that all queues are cleared and no backlog in the connections, the key event
7049 // can finally go to the newly focused "mUnfocusedWindow".
7050 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7051 mFocusedWindow->assertNoEvents();
7052 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007053 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007054}
7055
7056// When the touch stream is split across 2 windows, and one of them does not respond,
7057// then ANR should be raised and the touch should be canceled for the unresponsive window.
7058// The other window should not be affected by that.
7059TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7060 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007061 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7062 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7063 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007064 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007065 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066
7067 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007068 mDispatcher->notifyMotion(
7069 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7070 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007071
7072 const std::chrono::duration timeout =
7073 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007074 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007075
7076 mUnfocusedWindow->consumeMotionDown();
7077 mFocusedWindow->consumeMotionDown();
7078 // Focused window may or may not receive ACTION_MOVE
7079 // But it should definitely receive ACTION_CANCEL due to the ANR
7080 InputEvent* event;
7081 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7082 ASSERT_TRUE(moveOrCancelSequenceNum);
7083 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7084 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007085 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007086 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7087 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7088 mFocusedWindow->consumeMotionCancel();
7089 } else {
7090 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7091 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007092 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007093 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7094 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007095
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007096 mUnfocusedWindow->assertNoEvents();
7097 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007098 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007099}
7100
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007101/**
7102 * If we have no focused window, and a key comes in, we start the ANR timer.
7103 * The focused application should add a focused window before the timer runs out to prevent ANR.
7104 *
7105 * If the user touches another application during this time, the key should be dropped.
7106 * Next, if a new focused window comes in, without toggling the focused application,
7107 * then no ANR should occur.
7108 *
7109 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7110 * but in some cases the policy may not update the focused application.
7111 */
7112TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7113 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7114 std::make_shared<FakeApplicationHandle>();
7115 focusedApplication->setDispatchingTimeout(60ms);
7116 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7117 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7118 mFocusedWindow->setFocusable(false);
7119
7120 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7121 mFocusedWindow->consumeFocusEvent(false);
7122
7123 // Send a key. The ANR timer should start because there is no focused window.
7124 // 'focusedApplication' will get blamed if this timer completes.
7125 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007126 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007127 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7128 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7129 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007131
7132 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7133 // then the injected touches won't cause the focused event to get dropped.
7134 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7135 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7136 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7137 // For this test, it means that the key would get delivered to the window once it becomes
7138 // focused.
7139 std::this_thread::sleep_for(10ms);
7140
7141 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007142 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7143 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7144 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007145
7146 // We do not consume the motion right away, because that would require dispatcher to first
7147 // process (== drop) the key event, and by that time, ANR will be raised.
7148 // Set the focused window first.
7149 mFocusedWindow->setFocusable(true);
7150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7151 setFocusedWindow(mFocusedWindow);
7152 mFocusedWindow->consumeFocusEvent(true);
7153 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7154 // to another application. This could be a bug / behaviour in the policy.
7155
7156 mUnfocusedWindow->consumeMotionDown();
7157
7158 ASSERT_TRUE(mDispatcher->waitForIdle());
7159 // Should not ANR because we actually have a focused window. It was just added too slowly.
7160 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7161}
7162
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007163// These tests ensure we cannot send touch events to a window that's positioned behind a window
7164// that has feature NO_INPUT_CHANNEL.
7165// Layout:
7166// Top (closest to user)
7167// mNoInputWindow (above all windows)
7168// mBottomWindow
7169// Bottom (furthest from user)
7170class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7171 virtual void SetUp() override {
7172 InputDispatcherTest::SetUp();
7173
7174 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007175 mNoInputWindow =
7176 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7177 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007178 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007179 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007180 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7181 // It's perfectly valid for this window to not have an associated input channel
7182
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007183 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7184 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007185 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7186
7187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7188 }
7189
7190protected:
7191 std::shared_ptr<FakeApplicationHandle> mApplication;
7192 sp<FakeWindowHandle> mNoInputWindow;
7193 sp<FakeWindowHandle> mBottomWindow;
7194};
7195
7196TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7197 PointF touchedPoint = {10, 10};
7198
Prabir Pradhan678438e2023-04-13 19:32:51 +00007199 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7200 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7201 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007202
7203 mNoInputWindow->assertNoEvents();
7204 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7205 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7206 // and therefore should prevent mBottomWindow from receiving touches
7207 mBottomWindow->assertNoEvents();
7208}
7209
7210/**
7211 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7212 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7213 */
7214TEST_F(InputDispatcherMultiWindowOcclusionTests,
7215 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007216 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7217 "Window with input channel and NO_INPUT_CHANNEL",
7218 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007219
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007220 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007221 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7222 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7223
7224 PointF touchedPoint = {10, 10};
7225
Prabir Pradhan678438e2023-04-13 19:32:51 +00007226 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7227 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7228 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007229
7230 mNoInputWindow->assertNoEvents();
7231 mBottomWindow->assertNoEvents();
7232}
7233
Vishnu Nair958da932020-08-21 17:12:37 -07007234class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7235protected:
7236 std::shared_ptr<FakeApplicationHandle> mApp;
7237 sp<FakeWindowHandle> mWindow;
7238 sp<FakeWindowHandle> mMirror;
7239
7240 virtual void SetUp() override {
7241 InputDispatcherTest::SetUp();
7242 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007243 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7244 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7245 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7247 mWindow->setFocusable(true);
7248 mMirror->setFocusable(true);
7249 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7250 }
7251};
7252
7253TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7254 // Request focus on a mirrored window
7255 setFocusedWindow(mMirror);
7256
7257 // window gets focused
7258 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7260 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007261 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7262}
7263
7264// A focused & mirrored window remains focused only if the window and its mirror are both
7265// focusable.
7266TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7267 setFocusedWindow(mMirror);
7268
7269 // window gets focused
7270 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7272 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007273 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7275 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007276 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7277
7278 mMirror->setFocusable(false);
7279 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7280
7281 // window loses focus since one of the windows associated with the token in not focusable
7282 mWindow->consumeFocusEvent(false);
7283
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007284 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7285 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007286 mWindow->assertNoEvents();
7287}
7288
7289// A focused & mirrored window remains focused until the window and its mirror both become
7290// invisible.
7291TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7292 setFocusedWindow(mMirror);
7293
7294 // window gets focused
7295 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7297 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007298 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7300 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007301 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7302
7303 mMirror->setVisible(false);
7304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7305
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7307 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007308 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7310 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007311 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7312
7313 mWindow->setVisible(false);
7314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7315
7316 // window loses focus only after all windows associated with the token become invisible.
7317 mWindow->consumeFocusEvent(false);
7318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007319 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7320 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007321 mWindow->assertNoEvents();
7322}
7323
7324// A focused & mirrored window remains focused until both windows are removed.
7325TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7326 setFocusedWindow(mMirror);
7327
7328 // window gets focused
7329 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7331 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007332 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7334 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007335 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7336
7337 // single window is removed but the window token remains focused
7338 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7341 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007342 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7344 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007345 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7346
7347 // Both windows are removed
7348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7349 mWindow->consumeFocusEvent(false);
7350
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007351 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7352 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007353 mWindow->assertNoEvents();
7354}
7355
7356// Focus request can be pending until one window becomes visible.
7357TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7358 // Request focus on an invisible mirror.
7359 mWindow->setVisible(false);
7360 mMirror->setVisible(false);
7361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7362 setFocusedWindow(mMirror);
7363
7364 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007366 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7367 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007368
7369 mMirror->setVisible(true);
7370 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7371
7372 // window gets focused
7373 mWindow->consumeFocusEvent(true);
7374 // window gets the pending key event
7375 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7376}
Prabir Pradhan99987712020-11-10 18:43:05 -08007377
7378class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7379protected:
7380 std::shared_ptr<FakeApplicationHandle> mApp;
7381 sp<FakeWindowHandle> mWindow;
7382 sp<FakeWindowHandle> mSecondWindow;
7383
7384 void SetUp() override {
7385 InputDispatcherTest::SetUp();
7386 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007387 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007388 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007389 mSecondWindow =
7390 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007391 mSecondWindow->setFocusable(true);
7392
7393 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7395
7396 setFocusedWindow(mWindow);
7397 mWindow->consumeFocusEvent(true);
7398 }
7399
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007400 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007401 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007402 }
7403
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007404 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7405 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007406 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007407 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7408 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007409 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007410 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007411 }
7412};
7413
7414TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7415 // Ensure that capture cannot be obtained for unfocused windows.
7416 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7417 mFakePolicy->assertSetPointerCaptureNotCalled();
7418 mSecondWindow->assertNoEvents();
7419
7420 // Ensure that capture can be enabled from the focus window.
7421 requestAndVerifyPointerCapture(mWindow, true);
7422
7423 // Ensure that capture cannot be disabled from a window that does not have capture.
7424 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7425 mFakePolicy->assertSetPointerCaptureNotCalled();
7426
7427 // Ensure that capture can be disabled from the window with capture.
7428 requestAndVerifyPointerCapture(mWindow, false);
7429}
7430
7431TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007432 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007433
7434 setFocusedWindow(mSecondWindow);
7435
7436 // Ensure that the capture disabled event was sent first.
7437 mWindow->consumeCaptureEvent(false);
7438 mWindow->consumeFocusEvent(false);
7439 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007440 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007441
7442 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007443 notifyPointerCaptureChanged({});
7444 notifyPointerCaptureChanged(request);
7445 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007446 mWindow->assertNoEvents();
7447 mSecondWindow->assertNoEvents();
7448 mFakePolicy->assertSetPointerCaptureNotCalled();
7449}
7450
7451TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007452 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007453
7454 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007455 notifyPointerCaptureChanged({});
7456 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007457
7458 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007459 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007460 mWindow->consumeCaptureEvent(false);
7461 mWindow->assertNoEvents();
7462}
7463
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007464TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7465 requestAndVerifyPointerCapture(mWindow, true);
7466
7467 // The first window loses focus.
7468 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007469 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007470 mWindow->consumeCaptureEvent(false);
7471
7472 // Request Pointer Capture from the second window before the notification from InputReader
7473 // arrives.
7474 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007475 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007476
7477 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007478 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007479
7480 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007481 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007482
7483 mSecondWindow->consumeFocusEvent(true);
7484 mSecondWindow->consumeCaptureEvent(true);
7485}
7486
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007487TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7488 // App repeatedly enables and disables capture.
7489 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7490 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7491 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7492 mFakePolicy->assertSetPointerCaptureCalled(false);
7493 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7494 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7495
7496 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7497 // first request is now stale, this should do nothing.
7498 notifyPointerCaptureChanged(firstRequest);
7499 mWindow->assertNoEvents();
7500
7501 // InputReader notifies that the second request was enabled.
7502 notifyPointerCaptureChanged(secondRequest);
7503 mWindow->consumeCaptureEvent(true);
7504}
7505
Prabir Pradhan7092e262022-05-03 16:51:09 +00007506TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7507 requestAndVerifyPointerCapture(mWindow, true);
7508
7509 // App toggles pointer capture off and on.
7510 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7511 mFakePolicy->assertSetPointerCaptureCalled(false);
7512
7513 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7514 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7515
7516 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7517 // preceding "disable" request.
7518 notifyPointerCaptureChanged(enableRequest);
7519
7520 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7521 // any notifications.
7522 mWindow->assertNoEvents();
7523}
7524
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007525class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7526protected:
7527 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007528
7529 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7530 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7531
7532 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7533 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7534
7535 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7536 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7537 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7538 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7539 MAXIMUM_OBSCURING_OPACITY);
7540
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007541 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007542 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007543 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007544
7545 sp<FakeWindowHandle> mTouchWindow;
7546
7547 virtual void SetUp() override {
7548 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007549 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007550 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7551 }
7552
7553 virtual void TearDown() override {
7554 InputDispatcherTest::TearDown();
7555 mTouchWindow.clear();
7556 }
7557
chaviw3277faf2021-05-19 16:45:23 -05007558 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7559 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007560 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007561 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007562 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007563 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007564 return window;
7565 }
7566
7567 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7568 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7569 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007570 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007571 // Generate an arbitrary PID based on the UID
7572 window->setOwnerInfo(1777 + (uid % 10000), uid);
7573 return window;
7574 }
7575
7576 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007577 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7578 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7579 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007580 }
7581};
7582
7583TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007584 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007585 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007587
7588 touch();
7589
7590 mTouchWindow->assertNoEvents();
7591}
7592
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007593TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007594 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7595 const sp<FakeWindowHandle>& w =
7596 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7597 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7598
7599 touch();
7600
7601 mTouchWindow->assertNoEvents();
7602}
7603
7604TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007605 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7606 const sp<FakeWindowHandle>& w =
7607 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7609
7610 touch();
7611
7612 w->assertNoEvents();
7613}
7614
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007615TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007616 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007618
7619 touch();
7620
7621 mTouchWindow->consumeAnyMotionDown();
7622}
7623
7624TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007625 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007626 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007627 w->setFrame(Rect(0, 0, 50, 50));
7628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007629
7630 touch({PointF{100, 100}});
7631
7632 mTouchWindow->consumeAnyMotionDown();
7633}
7634
7635TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007636 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007637 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007638 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7639
7640 touch();
7641
7642 mTouchWindow->consumeAnyMotionDown();
7643}
7644
7645TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7646 const sp<FakeWindowHandle>& w =
7647 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007649
7650 touch();
7651
7652 mTouchWindow->consumeAnyMotionDown();
7653}
7654
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007655TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7656 const sp<FakeWindowHandle>& w =
7657 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7658 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7659
7660 touch();
7661
7662 w->assertNoEvents();
7663}
7664
7665/**
7666 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7667 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7668 * window, the occluding window will still receive ACTION_OUTSIDE event.
7669 */
7670TEST_F(InputDispatcherUntrustedTouchesTest,
7671 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7672 const sp<FakeWindowHandle>& w =
7673 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007674 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7676
7677 touch();
7678
7679 w->consumeMotionOutside();
7680}
7681
7682TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7683 const sp<FakeWindowHandle>& w =
7684 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007685 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7687
7688 touch();
7689
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007690 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007691}
7692
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007693TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007694 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007695 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7696 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7698
7699 touch();
7700
7701 mTouchWindow->consumeAnyMotionDown();
7702}
7703
7704TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7705 const sp<FakeWindowHandle>& w =
7706 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7707 MAXIMUM_OBSCURING_OPACITY);
7708 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007709
7710 touch();
7711
7712 mTouchWindow->consumeAnyMotionDown();
7713}
7714
7715TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007716 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007717 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7718 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007719 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7720
7721 touch();
7722
7723 mTouchWindow->assertNoEvents();
7724}
7725
7726TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7727 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7728 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007729 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7730 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007731 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007732 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7733 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7735
7736 touch();
7737
7738 mTouchWindow->assertNoEvents();
7739}
7740
7741TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7742 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7743 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007744 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7745 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007746 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007747 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7748 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7750
7751 touch();
7752
7753 mTouchWindow->consumeAnyMotionDown();
7754}
7755
7756TEST_F(InputDispatcherUntrustedTouchesTest,
7757 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7758 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007759 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7760 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007761 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007762 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7763 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007764 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7765
7766 touch();
7767
7768 mTouchWindow->consumeAnyMotionDown();
7769}
7770
7771TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7772 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007773 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7774 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007775 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007776 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7777 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007779
7780 touch();
7781
7782 mTouchWindow->assertNoEvents();
7783}
7784
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007785TEST_F(InputDispatcherUntrustedTouchesTest,
7786 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7787 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007788 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7789 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007790 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007791 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7792 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7794
7795 touch();
7796
7797 mTouchWindow->assertNoEvents();
7798}
7799
7800TEST_F(InputDispatcherUntrustedTouchesTest,
7801 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7802 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007803 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7804 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007805 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007806 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7807 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7809
7810 touch();
7811
7812 mTouchWindow->consumeAnyMotionDown();
7813}
7814
7815TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7816 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007817 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7818 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7820
7821 touch();
7822
7823 mTouchWindow->consumeAnyMotionDown();
7824}
7825
7826TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7827 const sp<FakeWindowHandle>& w =
7828 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7829 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7830
7831 touch();
7832
7833 mTouchWindow->consumeAnyMotionDown();
7834}
7835
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007836TEST_F(InputDispatcherUntrustedTouchesTest,
7837 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7838 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7839 const sp<FakeWindowHandle>& w =
7840 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7841 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7842
7843 touch();
7844
7845 mTouchWindow->assertNoEvents();
7846}
7847
7848TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7849 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7850 const sp<FakeWindowHandle>& w =
7851 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7853
7854 touch();
7855
7856 mTouchWindow->consumeAnyMotionDown();
7857}
7858
7859TEST_F(InputDispatcherUntrustedTouchesTest,
7860 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7861 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7862 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007863 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7864 OPACITY_ABOVE_THRESHOLD);
7865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7866
7867 touch();
7868
7869 mTouchWindow->consumeAnyMotionDown();
7870}
7871
7872TEST_F(InputDispatcherUntrustedTouchesTest,
7873 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7874 const sp<FakeWindowHandle>& w1 =
7875 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7876 OPACITY_BELOW_THRESHOLD);
7877 const sp<FakeWindowHandle>& w2 =
7878 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7879 OPACITY_BELOW_THRESHOLD);
7880 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7881
7882 touch();
7883
7884 mTouchWindow->assertNoEvents();
7885}
7886
7887/**
7888 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7889 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7890 * (which alone would result in allowing touches) does not affect the blocking behavior.
7891 */
7892TEST_F(InputDispatcherUntrustedTouchesTest,
7893 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7894 const sp<FakeWindowHandle>& wB =
7895 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7896 OPACITY_BELOW_THRESHOLD);
7897 const sp<FakeWindowHandle>& wC =
7898 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7899 OPACITY_BELOW_THRESHOLD);
7900 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7901
7902 touch();
7903
7904 mTouchWindow->assertNoEvents();
7905}
7906
7907/**
7908 * This test is testing that a window from a different UID but with same application token doesn't
7909 * block the touch. Apps can share the application token for close UI collaboration for example.
7910 */
7911TEST_F(InputDispatcherUntrustedTouchesTest,
7912 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7913 const sp<FakeWindowHandle>& w =
7914 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7915 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007916 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7917
7918 touch();
7919
7920 mTouchWindow->consumeAnyMotionDown();
7921}
7922
arthurhungb89ccb02020-12-30 16:19:01 +08007923class InputDispatcherDragTests : public InputDispatcherTest {
7924protected:
7925 std::shared_ptr<FakeApplicationHandle> mApp;
7926 sp<FakeWindowHandle> mWindow;
7927 sp<FakeWindowHandle> mSecondWindow;
7928 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007929 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007930 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7931 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007932
7933 void SetUp() override {
7934 InputDispatcherTest::SetUp();
7935 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007936 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007937 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007938
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007939 mSecondWindow =
7940 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007941 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007942
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007943 mSpyWindow =
7944 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007945 mSpyWindow->setSpy(true);
7946 mSpyWindow->setTrustedOverlay(true);
7947 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7948
arthurhungb89ccb02020-12-30 16:19:01 +08007949 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007951 }
7952
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007953 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7954 switch (fromSource) {
7955 case AINPUT_SOURCE_TOUCHSCREEN:
7956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7957 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7958 ADISPLAY_ID_DEFAULT, {50, 50}))
7959 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7960 break;
7961 case AINPUT_SOURCE_STYLUS:
7962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7963 injectMotionEvent(
7964 mDispatcher,
7965 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7966 AINPUT_SOURCE_STYLUS)
7967 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007968 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007969 .x(50)
7970 .y(50))
7971 .build()));
7972 break;
7973 case AINPUT_SOURCE_MOUSE:
7974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7975 injectMotionEvent(
7976 mDispatcher,
7977 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7978 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7979 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007980 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007981 .x(50)
7982 .y(50))
7983 .build()));
7984 break;
7985 default:
7986 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7987 }
arthurhungb89ccb02020-12-30 16:19:01 +08007988
7989 // Window should receive motion event.
7990 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007991 // Spy window should also receive motion event
7992 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007993 }
7994
7995 // Start performing drag, we will create a drag window and transfer touch to it.
7996 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7997 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007998 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007999 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008000 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008001 }
arthurhungb89ccb02020-12-30 16:19:01 +08008002
8003 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008004 mDragWindow =
8005 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008006 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008007 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008008 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008009
8010 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008011 bool transferred =
8012 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008013 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008014 if (transferred) {
8015 mWindow->consumeMotionCancel();
8016 mDragWindow->consumeMotionDown();
8017 }
8018 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008019 }
8020};
8021
8022TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008023 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008024
8025 // Move on window.
8026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8027 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8028 ADISPLAY_ID_DEFAULT, {50, 50}))
8029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8030 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8031 mWindow->consumeDragEvent(false, 50, 50);
8032 mSecondWindow->assertNoEvents();
8033
8034 // Move to another window.
8035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8036 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8037 ADISPLAY_ID_DEFAULT, {150, 50}))
8038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8039 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8040 mWindow->consumeDragEvent(true, 150, 50);
8041 mSecondWindow->consumeDragEvent(false, 50, 50);
8042
8043 // Move back to original window.
8044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8045 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8046 ADISPLAY_ID_DEFAULT, {50, 50}))
8047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8048 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8049 mWindow->consumeDragEvent(false, 50, 50);
8050 mSecondWindow->consumeDragEvent(true, -50, 50);
8051
8052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8053 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8055 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8056 mWindow->assertNoEvents();
8057 mSecondWindow->assertNoEvents();
8058}
8059
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008060TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008061 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008062
8063 // No cancel event after drag start
8064 mSpyWindow->assertNoEvents();
8065
8066 const MotionEvent secondFingerDownEvent =
8067 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8068 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008069 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8070 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008071 .build();
8072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8073 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8074 InputEventInjectionSync::WAIT_FOR_RESULT))
8075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8076
8077 // Receives cancel for first pointer after next pointer down
8078 mSpyWindow->consumeMotionCancel();
8079 mSpyWindow->consumeMotionDown();
8080
8081 mSpyWindow->assertNoEvents();
8082}
8083
arthurhungf452d0b2021-01-06 00:19:52 +08008084TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008085 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008086
8087 // Move on window.
8088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8089 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8090 ADISPLAY_ID_DEFAULT, {50, 50}))
8091 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8092 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8093 mWindow->consumeDragEvent(false, 50, 50);
8094 mSecondWindow->assertNoEvents();
8095
8096 // Move to another window.
8097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8098 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8099 ADISPLAY_ID_DEFAULT, {150, 50}))
8100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8101 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8102 mWindow->consumeDragEvent(true, 150, 50);
8103 mSecondWindow->consumeDragEvent(false, 50, 50);
8104
8105 // drop to another window.
8106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8107 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8108 {150, 50}))
8109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8110 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8111 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8112 mWindow->assertNoEvents();
8113 mSecondWindow->assertNoEvents();
8114}
8115
arthurhung6d4bed92021-03-17 11:59:33 +08008116TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008117 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008118
8119 // Move on window and keep button pressed.
8120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8121 injectMotionEvent(mDispatcher,
8122 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8123 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008124 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008125 .build()))
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 and release button, expect to drop item.
8132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8133 injectMotionEvent(mDispatcher,
8134 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8135 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008136 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008137 .build()))
8138 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8139 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8140 mWindow->assertNoEvents();
8141 mSecondWindow->assertNoEvents();
8142 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8143
8144 // nothing to the window.
8145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8146 injectMotionEvent(mDispatcher,
8147 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8148 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008149 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008150 .build()))
8151 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8152 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8153 mWindow->assertNoEvents();
8154 mSecondWindow->assertNoEvents();
8155}
8156
Arthur Hung54745652022-04-20 07:17:41 +00008157TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008158 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008159
8160 // Set second window invisible.
8161 mSecondWindow->setVisible(false);
8162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8163
8164 // Move on window.
8165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8166 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8167 ADISPLAY_ID_DEFAULT, {50, 50}))
8168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8169 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8170 mWindow->consumeDragEvent(false, 50, 50);
8171 mSecondWindow->assertNoEvents();
8172
8173 // Move to another window.
8174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8175 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8176 ADISPLAY_ID_DEFAULT, {150, 50}))
8177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8178 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8179 mWindow->consumeDragEvent(true, 150, 50);
8180 mSecondWindow->assertNoEvents();
8181
8182 // drop to another window.
8183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8184 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8185 {150, 50}))
8186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8187 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8188 mFakePolicy->assertDropTargetEquals(nullptr);
8189 mWindow->assertNoEvents();
8190 mSecondWindow->assertNoEvents();
8191}
8192
Arthur Hung54745652022-04-20 07:17:41 +00008193TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008194 // Ensure window could track pointerIds if it didn't support split touch.
8195 mWindow->setPreventSplitting(true);
8196
Arthur Hung54745652022-04-20 07:17:41 +00008197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8198 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8199 {50, 50}))
8200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8201 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8202
8203 const MotionEvent secondFingerDownEvent =
8204 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8205 .displayId(ADISPLAY_ID_DEFAULT)
8206 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008207 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8208 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008209 .build();
8210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8211 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8212 InputEventInjectionSync::WAIT_FOR_RESULT))
8213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008214 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008215
8216 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008217 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008218}
8219
8220TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8221 // First down on second window.
8222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8223 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8224 {150, 50}))
8225 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8226
8227 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8228
8229 // Second down on first window.
8230 const MotionEvent secondFingerDownEvent =
8231 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8232 .displayId(ADISPLAY_ID_DEFAULT)
8233 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008234 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8235 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008236 .build();
8237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8238 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8239 InputEventInjectionSync::WAIT_FOR_RESULT))
8240 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8241 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8242
8243 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008244 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008245
8246 // Move on window.
8247 const MotionEvent secondFingerMoveEvent =
8248 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8249 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008250 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8251 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008252 .build();
8253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8254 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8255 InputEventInjectionSync::WAIT_FOR_RESULT));
8256 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8257 mWindow->consumeDragEvent(false, 50, 50);
8258 mSecondWindow->consumeMotionMove();
8259
8260 // Release the drag pointer should perform drop.
8261 const MotionEvent secondFingerUpEvent =
8262 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8263 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008264 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8265 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008266 .build();
8267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8268 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8269 InputEventInjectionSync::WAIT_FOR_RESULT));
8270 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8271 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8272 mWindow->assertNoEvents();
8273 mSecondWindow->consumeMotionMove();
8274}
8275
Arthur Hung3915c1f2022-05-31 07:17:17 +00008276TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008277 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008278
8279 // Update window of second display.
8280 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008281 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008282 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8283
8284 // Let second display has a touch state.
8285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8286 injectMotionEvent(mDispatcher,
8287 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8288 AINPUT_SOURCE_TOUCHSCREEN)
8289 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008290 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008291 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008292 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008293 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008294 // Update window again.
8295 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8296
8297 // Move on window.
8298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8299 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8300 ADISPLAY_ID_DEFAULT, {50, 50}))
8301 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8302 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8303 mWindow->consumeDragEvent(false, 50, 50);
8304 mSecondWindow->assertNoEvents();
8305
8306 // Move to another window.
8307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8308 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8309 ADISPLAY_ID_DEFAULT, {150, 50}))
8310 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8311 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8312 mWindow->consumeDragEvent(true, 150, 50);
8313 mSecondWindow->consumeDragEvent(false, 50, 50);
8314
8315 // drop to another window.
8316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8317 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8318 {150, 50}))
8319 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8320 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8321 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8322 mWindow->assertNoEvents();
8323 mSecondWindow->assertNoEvents();
8324}
8325
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008326TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8327 startDrag(true, AINPUT_SOURCE_MOUSE);
8328 // Move on window.
8329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8330 injectMotionEvent(mDispatcher,
8331 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8332 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8333 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008334 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008335 .x(50)
8336 .y(50))
8337 .build()))
8338 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8339 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8340 mWindow->consumeDragEvent(false, 50, 50);
8341 mSecondWindow->assertNoEvents();
8342
8343 // Move to another window.
8344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8345 injectMotionEvent(mDispatcher,
8346 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8347 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8348 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008349 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008350 .x(150)
8351 .y(50))
8352 .build()))
8353 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8354 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8355 mWindow->consumeDragEvent(true, 150, 50);
8356 mSecondWindow->consumeDragEvent(false, 50, 50);
8357
8358 // drop to another window.
8359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8360 injectMotionEvent(mDispatcher,
8361 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8362 .buttonState(0)
8363 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008364 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008365 .x(150)
8366 .y(50))
8367 .build()))
8368 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8369 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8370 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8371 mWindow->assertNoEvents();
8372 mSecondWindow->assertNoEvents();
8373}
8374
Vishnu Nair062a8672021-09-03 16:07:44 -07008375class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8376
8377TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008379 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8380 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008381 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008382 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8383 window->setFocusable(true);
8384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8385 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008386 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008387
8388 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008389 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008390 window->assertNoEvents();
8391
Prabir Pradhan678438e2023-04-13 19:32:51 +00008392 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8393 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008394 window->assertNoEvents();
8395
8396 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008397 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8399
Prabir Pradhan678438e2023-04-13 19:32:51 +00008400 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008401 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8402
Prabir Pradhan678438e2023-04-13 19:32:51 +00008403 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8404 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008405 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8406 window->assertNoEvents();
8407}
8408
8409TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8410 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8411 std::make_shared<FakeApplicationHandle>();
8412 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008413 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8414 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008415 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8416 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008417 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008419 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8420 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008421 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008422 window->setOwnerInfo(222, 222);
8423 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8424 window->setFocusable(true);
8425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8426 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008427 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008428
8429 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008430 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008431 window->assertNoEvents();
8432
Prabir Pradhan678438e2023-04-13 19:32:51 +00008433 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8434 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008435 window->assertNoEvents();
8436
8437 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008438 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008439 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8440
Prabir Pradhan678438e2023-04-13 19:32:51 +00008441 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008442 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8443
Prabir Pradhan678438e2023-04-13 19:32:51 +00008444 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8445 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008446 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8447 window->assertNoEvents();
8448}
8449
8450TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8451 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8452 std::make_shared<FakeApplicationHandle>();
8453 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008454 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8455 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008456 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8457 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008458 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008459 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008460 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8461 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008462 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008463 window->setOwnerInfo(222, 222);
8464 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8465 window->setFocusable(true);
8466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8467 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008468 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008469
8470 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008471 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008472 window->assertNoEvents();
8473
Prabir Pradhan678438e2023-04-13 19:32:51 +00008474 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8475 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008476 window->assertNoEvents();
8477
8478 // When the window is no longer obscured because it went on top, it should get input
8479 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8480
Prabir Pradhan678438e2023-04-13 19:32:51 +00008481 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008482 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8483
Prabir Pradhan678438e2023-04-13 19:32:51 +00008484 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8485 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008486 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8487 window->assertNoEvents();
8488}
8489
Antonio Kantekf16f2832021-09-28 04:39:20 +00008490class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8491protected:
8492 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008493 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008494 sp<FakeWindowHandle> mWindow;
8495 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008496 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008497
8498 void SetUp() override {
8499 InputDispatcherTest::SetUp();
8500
8501 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008502 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008503 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008504 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008505 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008506 mSecondWindow =
8507 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008508 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008509 mThirdWindow =
8510 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8511 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8512 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008513
8514 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008515 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8516 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8517 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008518 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008519
Antonio Kantek15beb512022-06-13 22:35:41 +00008520 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008521 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008522 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008523 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8524 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008525 mThirdWindow->assertNoEvents();
8526 }
8527
8528 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8529 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008530 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008531 SECOND_DISPLAY_ID)) {
8532 mWindow->assertNoEvents();
8533 mSecondWindow->assertNoEvents();
8534 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008535 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008536 }
8537
Antonio Kantek15beb512022-06-13 22:35:41 +00008538 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8539 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008540 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8541 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008542 mWindow->consumeTouchModeEvent(inTouchMode);
8543 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008544 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008545 }
8546};
8547
Antonio Kantek26defcf2022-02-08 01:12:27 +00008548TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008549 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008550 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8551 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008552 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008553}
8554
Antonio Kantek26defcf2022-02-08 01:12:27 +00008555TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8556 const WindowInfo& windowInfo = *mWindow->getInfo();
8557 int32_t ownerPid = windowInfo.ownerPid;
8558 int32_t ownerUid = windowInfo.ownerUid;
8559 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8560 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008561 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008562 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008563 mWindow->assertNoEvents();
8564 mSecondWindow->assertNoEvents();
8565}
8566
8567TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8568 const WindowInfo& windowInfo = *mWindow->getInfo();
8569 int32_t ownerPid = windowInfo.ownerPid;
8570 int32_t ownerUid = windowInfo.ownerUid;
8571 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008572 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008573 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008574}
8575
Antonio Kantekf16f2832021-09-28 04:39:20 +00008576TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008577 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008578 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8579 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008580 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008581 mWindow->assertNoEvents();
8582 mSecondWindow->assertNoEvents();
8583}
8584
Antonio Kantek15beb512022-06-13 22:35:41 +00008585TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8586 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8587 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8588 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008589 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008590 mWindow->assertNoEvents();
8591 mSecondWindow->assertNoEvents();
8592 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8593}
8594
Antonio Kantek48710e42022-03-24 14:19:30 -07008595TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8596 // Interact with the window first.
8597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8598 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8599 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8600
8601 // Then remove focus.
8602 mWindow->setFocusable(false);
8603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8604
8605 // Assert that caller can switch touch mode by owning one of the last interacted window.
8606 const WindowInfo& windowInfo = *mWindow->getInfo();
8607 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8608 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008609 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008610}
8611
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008612class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8613public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008614 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008615 std::shared_ptr<FakeApplicationHandle> application =
8616 std::make_shared<FakeApplicationHandle>();
8617 std::string name = "Fake Spy ";
8618 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008619 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8620 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008621 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008622 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008623 return spy;
8624 }
8625
8626 sp<FakeWindowHandle> createForeground() {
8627 std::shared_ptr<FakeApplicationHandle> application =
8628 std::make_shared<FakeApplicationHandle>();
8629 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008630 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8631 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008632 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008633 return window;
8634 }
8635
8636private:
8637 int mSpyCount{0};
8638};
8639
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008640using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008641/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008642 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8643 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008644TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8645 ScopedSilentDeath _silentDeath;
8646
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008647 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008648 spy->setTrustedOverlay(false);
8649 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8650 ".* not a trusted overlay");
8651}
8652
8653/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008654 * Input injection into a display with a spy window but no foreground windows should succeed.
8655 */
8656TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008657 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008658 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8659
8660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8661 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8663 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8664}
8665
8666/**
8667 * Verify the order in which different input windows receive events. The touched foreground window
8668 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8669 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8670 * receive events before ones belows it.
8671 *
8672 * Here, we set up a scenario with four windows in the following Z order from the top:
8673 * spy1, spy2, window, spy3.
8674 * We then inject an event and verify that the foreground "window" receives it first, followed by
8675 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8676 * window.
8677 */
8678TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8679 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008680 auto spy1 = createSpy();
8681 auto spy2 = createSpy();
8682 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8684 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8685 const size_t numChannels = channels.size();
8686
Michael Wright8e9a8562022-02-09 13:44:29 +00008687 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008688 if (!epollFd.ok()) {
8689 FAIL() << "Failed to create epoll fd";
8690 }
8691
8692 for (size_t i = 0; i < numChannels; i++) {
8693 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8694 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8695 FAIL() << "Failed to add fd to epoll";
8696 }
8697 }
8698
8699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8700 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8702
8703 std::vector<size_t> eventOrder;
8704 std::vector<struct epoll_event> events(numChannels);
8705 for (;;) {
8706 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8707 (100ms).count());
8708 if (nFds < 0) {
8709 FAIL() << "Failed to call epoll_wait";
8710 }
8711 if (nFds == 0) {
8712 break; // epoll_wait timed out
8713 }
8714 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008715 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008716 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008717 channels[i]->consumeMotionDown();
8718 }
8719 }
8720
8721 // Verify the order in which the events were received.
8722 EXPECT_EQ(3u, eventOrder.size());
8723 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8724 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8725 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8726}
8727
8728/**
8729 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8730 */
8731TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8732 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008733 auto spy = createSpy();
8734 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8736
8737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8740 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8741 spy->assertNoEvents();
8742}
8743
8744/**
8745 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8746 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8747 * to the window.
8748 */
8749TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8750 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008751 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008752 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8753 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8754
8755 // Inject an event outside the spy window's touchable region.
8756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8757 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8759 window->consumeMotionDown();
8760 spy->assertNoEvents();
8761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8762 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8764 window->consumeMotionUp();
8765 spy->assertNoEvents();
8766
8767 // Inject an event inside the spy window's touchable region.
8768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8769 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8770 {5, 10}))
8771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8772 window->consumeMotionDown();
8773 spy->consumeMotionDown();
8774}
8775
8776/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008777 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008778 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008779 */
8780TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8781 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008782 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008783 auto spy = createSpy();
8784 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008785 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008786 spy->setFrame(Rect{0, 0, 20, 20});
8787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8788
8789 // Inject an event outside the spy window's frame and touchable region.
8790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008791 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8792 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008793 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8794 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008795 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008796}
8797
8798/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008799 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8800 * pointers that are down within its bounds.
8801 */
8802TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8803 auto windowLeft = createForeground();
8804 windowLeft->setFrame({0, 0, 100, 200});
8805 auto windowRight = createForeground();
8806 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008807 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008808 spy->setFrame({0, 0, 200, 200});
8809 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8810
8811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8812 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8813 {50, 50}))
8814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8815 windowLeft->consumeMotionDown();
8816 spy->consumeMotionDown();
8817
8818 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008819 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008820 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008821 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8822 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008823 .build();
8824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8825 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8826 InputEventInjectionSync::WAIT_FOR_RESULT))
8827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8828 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008829 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008830}
8831
8832/**
8833 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8834 * the spy should receive the second pointer with ACTION_DOWN.
8835 */
8836TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8837 auto window = createForeground();
8838 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008839 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008840 spyRight->setFrame({100, 0, 200, 200});
8841 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8842
8843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8844 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8845 {50, 50}))
8846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8847 window->consumeMotionDown();
8848 spyRight->assertNoEvents();
8849
8850 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008851 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008852 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008853 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8854 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008855 .build();
8856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8857 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8858 InputEventInjectionSync::WAIT_FOR_RESULT))
8859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008860 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008861 spyRight->consumeMotionDown();
8862}
8863
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008864/**
8865 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8866 * windows should be allowed to control split touch.
8867 */
8868TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008869 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008870 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008871 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008872 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008873
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008874 auto window = createForeground();
8875 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008876
8877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8878
8879 // First finger down, no window touched.
8880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8881 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8882 {100, 200}))
8883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8884 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8885 window->assertNoEvents();
8886
8887 // Second finger down on window, the window should receive touch down.
8888 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008889 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008890 .displayId(ADISPLAY_ID_DEFAULT)
8891 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008892 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8893 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008894 .build();
8895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8896 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8897 InputEventInjectionSync::WAIT_FOR_RESULT))
8898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8899
8900 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008901 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008902}
8903
8904/**
8905 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8906 * do not receive key events.
8907 */
8908TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008909 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008910 spy->setFocusable(false);
8911
8912 auto window = createForeground();
8913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8914 setFocusedWindow(window);
8915 window->consumeFocusEvent(true);
8916
8917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8918 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8919 window->consumeKeyDown(ADISPLAY_ID_NONE);
8920
8921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8922 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8923 window->consumeKeyUp(ADISPLAY_ID_NONE);
8924
8925 spy->assertNoEvents();
8926}
8927
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008928using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8929
8930/**
8931 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8932 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8933 */
8934TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8935 auto window = createForeground();
8936 auto spy1 = createSpy();
8937 auto spy2 = createSpy();
8938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8939
8940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8941 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8943 window->consumeMotionDown();
8944 spy1->consumeMotionDown();
8945 spy2->consumeMotionDown();
8946
8947 // Pilfer pointers from the second spy window.
8948 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8949 spy2->assertNoEvents();
8950 spy1->consumeMotionCancel();
8951 window->consumeMotionCancel();
8952
8953 // The rest of the gesture should only be sent to the second spy window.
8954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8955 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8956 ADISPLAY_ID_DEFAULT))
8957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8958 spy2->consumeMotionMove();
8959 spy1->assertNoEvents();
8960 window->assertNoEvents();
8961}
8962
8963/**
8964 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8965 * in the middle of the gesture.
8966 */
8967TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8968 auto window = createForeground();
8969 auto spy = createSpy();
8970 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8971
8972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8973 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8975 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8976 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8977
8978 window->releaseChannel();
8979
8980 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8981
8982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8983 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8985 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8986}
8987
8988/**
8989 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8990 * the spy, but not to any other windows.
8991 */
8992TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8993 auto spy = createSpy();
8994 auto window = createForeground();
8995
8996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8997
8998 // First finger down on the window and the spy.
8999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9000 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9001 {100, 200}))
9002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9003 spy->consumeMotionDown();
9004 window->consumeMotionDown();
9005
9006 // Spy window pilfers the pointers.
9007 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9008 window->consumeMotionCancel();
9009
9010 // Second finger down on the window and spy, but the window should not receive the pointer down.
9011 const MotionEvent secondFingerDownEvent =
9012 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9013 .displayId(ADISPLAY_ID_DEFAULT)
9014 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009015 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9016 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009017 .build();
9018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9019 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9020 InputEventInjectionSync::WAIT_FOR_RESULT))
9021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9022
Harry Cutts33476232023-01-30 19:57:29 +00009023 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009024
9025 // Third finger goes down outside all windows, so injection should fail.
9026 const MotionEvent thirdFingerDownEvent =
9027 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9028 .displayId(ADISPLAY_ID_DEFAULT)
9029 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009030 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9031 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9032 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009033 .build();
9034 ASSERT_EQ(InputEventInjectionResult::FAILED,
9035 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9036 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009037 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009038
9039 spy->assertNoEvents();
9040 window->assertNoEvents();
9041}
9042
9043/**
9044 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9045 */
9046TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9047 auto spy = createSpy();
9048 spy->setFrame(Rect(0, 0, 100, 100));
9049 auto window = createForeground();
9050 window->setFrame(Rect(0, 0, 200, 200));
9051
9052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9053
9054 // First finger down on the window only
9055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9056 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9057 {150, 150}))
9058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9059 window->consumeMotionDown();
9060
9061 // Second finger down on the spy and window
9062 const MotionEvent secondFingerDownEvent =
9063 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9064 .displayId(ADISPLAY_ID_DEFAULT)
9065 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009066 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9067 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009068 .build();
9069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9070 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9071 InputEventInjectionSync::WAIT_FOR_RESULT))
9072 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9073 spy->consumeMotionDown();
9074 window->consumeMotionPointerDown(1);
9075
9076 // Third finger down on the spy and window
9077 const MotionEvent thirdFingerDownEvent =
9078 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9079 .displayId(ADISPLAY_ID_DEFAULT)
9080 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009081 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9082 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9083 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009084 .build();
9085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9086 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9087 InputEventInjectionSync::WAIT_FOR_RESULT))
9088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9089 spy->consumeMotionPointerDown(1);
9090 window->consumeMotionPointerDown(2);
9091
9092 // Spy window pilfers the pointers.
9093 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9094 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9095 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9096
9097 spy->assertNoEvents();
9098 window->assertNoEvents();
9099}
9100
9101/**
9102 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9103 * other windows should be canceled. If this results in the cancellation of all pointers for some
9104 * window, then that window should receive ACTION_CANCEL.
9105 */
9106TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9107 auto spy = createSpy();
9108 spy->setFrame(Rect(0, 0, 100, 100));
9109 auto window = createForeground();
9110 window->setFrame(Rect(0, 0, 200, 200));
9111
9112 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9113
9114 // First finger down on both spy and window
9115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9116 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9117 {10, 10}))
9118 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9119 window->consumeMotionDown();
9120 spy->consumeMotionDown();
9121
9122 // Second finger down on the spy and window
9123 const MotionEvent secondFingerDownEvent =
9124 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9125 .displayId(ADISPLAY_ID_DEFAULT)
9126 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009127 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9128 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009129 .build();
9130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9131 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9132 InputEventInjectionSync::WAIT_FOR_RESULT))
9133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9134 spy->consumeMotionPointerDown(1);
9135 window->consumeMotionPointerDown(1);
9136
9137 // Spy window pilfers the pointers.
9138 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9139 window->consumeMotionCancel();
9140
9141 spy->assertNoEvents();
9142 window->assertNoEvents();
9143}
9144
9145/**
9146 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9147 * be sent to other windows
9148 */
9149TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9150 auto spy = createSpy();
9151 spy->setFrame(Rect(0, 0, 100, 100));
9152 auto window = createForeground();
9153 window->setFrame(Rect(0, 0, 200, 200));
9154
9155 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9156
9157 // First finger down on both window and spy
9158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9159 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9160 {10, 10}))
9161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9162 window->consumeMotionDown();
9163 spy->consumeMotionDown();
9164
9165 // Spy window pilfers the pointers.
9166 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9167 window->consumeMotionCancel();
9168
9169 // Second finger down on the window only
9170 const MotionEvent secondFingerDownEvent =
9171 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9172 .displayId(ADISPLAY_ID_DEFAULT)
9173 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009174 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9175 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009176 .build();
9177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9178 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9179 InputEventInjectionSync::WAIT_FOR_RESULT))
9180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9181 window->consumeMotionDown();
9182 window->assertNoEvents();
9183
9184 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9185 spy->consumeMotionMove();
9186 spy->assertNoEvents();
9187}
9188
Prabir Pradhand65552b2021-10-07 11:23:50 -07009189class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9190public:
9191 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9192 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9193 std::make_shared<FakeApplicationHandle>();
9194 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009195 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9196 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009197 overlay->setFocusable(false);
9198 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009199 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009200 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009201 overlay->setTrustedOverlay(true);
9202
9203 std::shared_ptr<FakeApplicationHandle> application =
9204 std::make_shared<FakeApplicationHandle>();
9205 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009206 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9207 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009208 window->setFocusable(true);
9209 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009210
9211 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9212 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9213 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009214 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009215 return {std::move(overlay), std::move(window)};
9216 }
9217
9218 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009219 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009220 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009221 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009222 }
9223
9224 void sendStylusEvent(int32_t action) {
9225 NotifyMotionArgs motionArgs =
9226 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9227 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009228 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009229 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009230 }
9231};
9232
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009233using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9234
9235TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9236 ScopedSilentDeath _silentDeath;
9237
Prabir Pradhand65552b2021-10-07 11:23:50 -07009238 auto [overlay, window] = setupStylusOverlayScenario();
9239 overlay->setTrustedOverlay(false);
9240 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9241 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9242 ".* not a trusted overlay");
9243}
9244
9245TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9246 auto [overlay, window] = setupStylusOverlayScenario();
9247 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9248
9249 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9250 overlay->consumeMotionDown();
9251 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9252 overlay->consumeMotionUp();
9253
9254 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9255 window->consumeMotionDown();
9256 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9257 window->consumeMotionUp();
9258
9259 overlay->assertNoEvents();
9260 window->assertNoEvents();
9261}
9262
9263TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9264 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009265 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009266 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9267
9268 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9269 overlay->consumeMotionDown();
9270 window->consumeMotionDown();
9271 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9272 overlay->consumeMotionUp();
9273 window->consumeMotionUp();
9274
9275 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9276 window->consumeMotionDown();
9277 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9278 window->consumeMotionUp();
9279
9280 overlay->assertNoEvents();
9281 window->assertNoEvents();
9282}
9283
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009284/**
9285 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9286 * The scenario is as follows:
9287 * - The stylus interceptor overlay is configured as a spy window.
9288 * - The stylus interceptor spy receives the start of a new stylus gesture.
9289 * - It pilfers pointers and then configures itself to no longer be a spy.
9290 * - The stylus interceptor continues to receive the rest of the gesture.
9291 */
9292TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9293 auto [overlay, window] = setupStylusOverlayScenario();
9294 overlay->setSpy(true);
9295 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9296
9297 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9298 overlay->consumeMotionDown();
9299 window->consumeMotionDown();
9300
9301 // The interceptor pilfers the pointers.
9302 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9303 window->consumeMotionCancel();
9304
9305 // The interceptor configures itself so that it is no longer a spy.
9306 overlay->setSpy(false);
9307 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9308
9309 // It continues to receive the rest of the stylus gesture.
9310 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9311 overlay->consumeMotionMove();
9312 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9313 overlay->consumeMotionUp();
9314
9315 window->assertNoEvents();
9316}
9317
Prabir Pradhan5735a322022-04-11 17:23:34 +00009318struct User {
9319 int32_t mPid;
9320 int32_t mUid;
9321 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9322 std::unique_ptr<InputDispatcher>& mDispatcher;
9323
9324 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9325 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9326
9327 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9328 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9329 ADISPLAY_ID_DEFAULT, {100, 200},
9330 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9331 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9332 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9333 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9334 }
9335
9336 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009337 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009338 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009339 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009340 mPolicyFlags);
9341 }
9342
9343 sp<FakeWindowHandle> createWindow() const {
9344 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9345 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009346 sp<FakeWindowHandle> window =
9347 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9348 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009349 window->setOwnerInfo(mPid, mUid);
9350 return window;
9351 }
9352};
9353
9354using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9355
9356TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9357 auto owner = User(mDispatcher, 10, 11);
9358 auto window = owner.createWindow();
9359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9360
9361 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9362 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9363 window->consumeMotionDown();
9364
9365 setFocusedWindow(window);
9366 window->consumeFocusEvent(true);
9367
9368 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9369 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9370 window->consumeKeyDown(ADISPLAY_ID_NONE);
9371}
9372
9373TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9374 auto owner = User(mDispatcher, 10, 11);
9375 auto window = owner.createWindow();
9376 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9377
9378 auto rando = User(mDispatcher, 20, 21);
9379 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9380 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9381
9382 setFocusedWindow(window);
9383 window->consumeFocusEvent(true);
9384
9385 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9386 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9387 window->assertNoEvents();
9388}
9389
9390TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9391 auto owner = User(mDispatcher, 10, 11);
9392 auto window = owner.createWindow();
9393 auto spy = owner.createWindow();
9394 spy->setSpy(true);
9395 spy->setTrustedOverlay(true);
9396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9397
9398 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9399 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9400 spy->consumeMotionDown();
9401 window->consumeMotionDown();
9402}
9403
9404TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9405 auto owner = User(mDispatcher, 10, 11);
9406 auto window = owner.createWindow();
9407
9408 auto rando = User(mDispatcher, 20, 21);
9409 auto randosSpy = rando.createWindow();
9410 randosSpy->setSpy(true);
9411 randosSpy->setTrustedOverlay(true);
9412 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9413
9414 // The event is targeted at owner's window, so injection should succeed, but the spy should
9415 // not receive the event.
9416 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9417 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9418 randosSpy->assertNoEvents();
9419 window->consumeMotionDown();
9420}
9421
9422TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9423 auto owner = User(mDispatcher, 10, 11);
9424 auto window = owner.createWindow();
9425
9426 auto rando = User(mDispatcher, 20, 21);
9427 auto randosSpy = rando.createWindow();
9428 randosSpy->setSpy(true);
9429 randosSpy->setTrustedOverlay(true);
9430 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9431
9432 // A user that has injection permission can inject into any window.
9433 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9434 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9435 ADISPLAY_ID_DEFAULT));
9436 randosSpy->consumeMotionDown();
9437 window->consumeMotionDown();
9438
9439 setFocusedWindow(randosSpy);
9440 randosSpy->consumeFocusEvent(true);
9441
9442 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9443 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9444 window->assertNoEvents();
9445}
9446
9447TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9448 auto owner = User(mDispatcher, 10, 11);
9449 auto window = owner.createWindow();
9450
9451 auto rando = User(mDispatcher, 20, 21);
9452 auto randosWindow = rando.createWindow();
9453 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9454 randosWindow->setWatchOutsideTouch(true);
9455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9456
9457 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9458 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9459 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9460 window->consumeMotionDown();
9461 randosWindow->consumeMotionOutside();
9462}
9463
Garfield Tane84e6f92019-08-29 17:28:41 -07009464} // namespace android::inputdispatcher