blob: 5e51bfc1ea765466bcabbbd1e1e0fabc9de11a42 [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 -0800208protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000209 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210
211public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000212 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800213
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800214 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700215 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700216 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700217 EXPECT_EQ(event.getDisplayId(), args.displayId);
218
219 const auto& keyEvent = static_cast<const KeyEvent&>(event);
220 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
221 EXPECT_EQ(keyEvent.getAction(), args.action);
222 });
Jackal Guof9696682018-10-05 12:23:23 +0800223 }
224
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700225 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
226 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700227 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 EXPECT_EQ(event.getDisplayId(), args.displayId);
229
230 const auto& motionEvent = static_cast<const MotionEvent&>(event);
231 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
232 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000233 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
234 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
235 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
236 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700237 });
Jackal Guof9696682018-10-05 12:23:23 +0800238 }
239
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700240 void assertFilterInputEventWasNotCalled() {
241 std::scoped_lock lock(mLock);
242 ASSERT_EQ(nullptr, mFilteredEvent);
243 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800244
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800245 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700246 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800247 ASSERT_TRUE(mConfigurationChangedTime)
248 << "Timed out waiting for configuration changed call";
249 ASSERT_EQ(*mConfigurationChangedTime, when);
250 mConfigurationChangedTime = std::nullopt;
251 }
252
253 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700254 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800256 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800257 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
258 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
259 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
260 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
261 mLastNotifySwitch = std::nullopt;
262 }
263
chaviwfd6d3512019-03-25 13:23:49 -0700264 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700265 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800266 ASSERT_EQ(touchedToken, mOnPointerDownToken);
267 mOnPointerDownToken.clear();
268 }
269
270 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700271 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800272 ASSERT_TRUE(mOnPointerDownToken == nullptr)
273 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700274 }
275
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700276 // This function must be called soon after the expected ANR timer starts,
277 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500278 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700279 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500280 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 std::unique_lock lock(mLock);
282 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 ASSERT_NO_FATAL_FAILURE(
285 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700287 }
288
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000289 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 const sp<WindowInfoHandle>& window) {
291 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
292 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
293 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500294 }
295
Prabir Pradhanedd96402022-02-15 01:46:16 -0800296 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
297 const sp<IBinder>& expectedToken,
298 int32_t expectedPid) {
299 std::unique_lock lock(mLock);
300 android::base::ScopedLockAssertion assumeLocked(mLock);
301 AnrResult result;
302 ASSERT_NO_FATAL_FAILURE(result =
303 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
304 const auto& [token, pid] = result;
305 ASSERT_EQ(expectedToken, token);
306 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500307 }
308
Prabir Pradhanedd96402022-02-15 01:46:16 -0800309 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000310 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500311 std::unique_lock lock(mLock);
312 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800313 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
314 const auto& [token, _] = result;
315 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000316 }
317
Prabir Pradhanedd96402022-02-15 01:46:16 -0800318 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
319 int32_t expectedPid) {
320 std::unique_lock lock(mLock);
321 android::base::ScopedLockAssertion assumeLocked(mLock);
322 AnrResult result;
323 ASSERT_NO_FATAL_FAILURE(
324 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
325 const auto& [token, pid] = result;
326 ASSERT_EQ(expectedToken, token);
327 ASSERT_EQ(expectedPid, pid);
328 }
329
330 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000331 sp<IBinder> getResponsiveWindowToken() {
332 std::unique_lock lock(mLock);
333 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800334 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
335 const auto& [token, _] = result;
336 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700337 }
338
339 void assertNotifyAnrWasNotCalled() {
340 std::scoped_lock lock(mLock);
341 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800342 ASSERT_TRUE(mAnrWindows.empty());
343 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500344 << "ANR was not called, but please also consume the 'connection is responsive' "
345 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700346 }
347
Garfield Tan1c7bc862020-01-28 13:24:04 -0800348 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
349 mConfig.keyRepeatTimeout = timeout;
350 mConfig.keyRepeatDelay = delay;
351 }
352
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000353 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800354 std::unique_lock lock(mLock);
355 base::ScopedLockAssertion assumeLocked(mLock);
356
357 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
358 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000359 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800360 enabled;
361 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
363 << ") to be called.";
364 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000366 auto request = *mPointerCaptureRequest;
367 mPointerCaptureRequest.reset();
368 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800369 }
370
371 void assertSetPointerCaptureNotCalled() {
372 std::unique_lock lock(mLock);
373 base::ScopedLockAssertion assumeLocked(mLock);
374
375 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000380 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800381 }
382
arthurhungf452d0b2021-01-06 00:19:52 +0800383 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
384 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800386 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800387 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800388 }
389
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800390 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
391 std::unique_lock lock(mLock);
392 base::ScopedLockAssertion assumeLocked(mLock);
393 std::optional<sp<IBinder>> receivedToken =
394 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
395 mNotifyInputChannelBroken);
396 ASSERT_TRUE(receivedToken.has_value());
397 ASSERT_EQ(token, *receivedToken);
398 }
399
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800400 /**
401 * Set policy timeout. A value of zero means next key will not be intercepted.
402 */
403 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
404 mInterceptKeyTimeout = timeout;
405 }
406
Michael Wrightd02c5b62014-02-10 15:10:22 -0800407private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700408 std::mutex mLock;
409 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
410 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
411 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
412 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800413
Prabir Pradhan99987712020-11-10 18:43:05 -0800414 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000415
416 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800417
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700418 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700419 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800420 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
421 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700422 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800423 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
424 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700425
arthurhungf452d0b2021-01-06 00:19:52 +0800426 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800427 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800428
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800429 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
430
Prabir Pradhanedd96402022-02-15 01:46:16 -0800431 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
432 // for a specific container to become non-empty. When the container is non-empty, return the
433 // first entry from the container and erase it.
434 template <class T>
435 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
436 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
437 // If there is an ANR, Dispatcher won't be idle because there are still events
438 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
439 // before checking if ANR was called.
440 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
441 // to provide it some time to act. 100ms seems reasonable.
442 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
443 const std::chrono::time_point start = std::chrono::steady_clock::now();
444 std::optional<T> token =
445 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
446 if (!token.has_value()) {
447 ADD_FAILURE() << "Did not receive the ANR callback";
448 return {};
449 }
450
451 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
452 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
453 // the dispatcher started counting before this function was called
454 if (std::chrono::abs(timeout - waited) > 100ms) {
455 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
457 << "ms, but waited "
458 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
459 << "ms instead";
460 }
461 return *token;
462 }
463
464 template <class T>
465 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
466 std::queue<T>& storage,
467 std::unique_lock<std::mutex>& lock,
468 std::condition_variable& condition)
469 REQUIRES(mLock) {
470 condition.wait_for(lock, timeout,
471 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
472 if (storage.empty()) {
473 ADD_FAILURE() << "Did not receive the expected callback";
474 return std::nullopt;
475 }
476 T item = storage.front();
477 storage.pop();
478 return std::make_optional(item);
479 }
480
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600481 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700482 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800483 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800484 }
485
Prabir Pradhanedd96402022-02-15 01:46:16 -0800486 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
487 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700488 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800489 ASSERT_TRUE(pid.has_value());
490 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700491 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500492 }
493
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
495 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500496 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800497 ASSERT_TRUE(pid.has_value());
498 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500499 mNotifyAnr.notify_all();
500 }
501
502 void notifyNoFocusedWindowAnr(
503 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
504 std::scoped_lock lock(mLock);
505 mAnrApplications.push(applicationHandle);
506 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800507 }
508
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800509 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
510 std::scoped_lock lock(mLock);
511 mBrokenInputChannels.push(connectionToken);
512 mNotifyInputChannelBroken.notify_all();
513 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800514
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600515 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700516
Chris Yef59a2f42020-10-16 12:55:26 -0700517 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
518 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
519 const std::vector<float>& values) override {}
520
521 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
522 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000523
Chris Yefb552902021-02-03 17:18:37 -0800524 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
525
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600526 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 *outConfig = mConfig;
528 }
529
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600530 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700531 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800532 switch (inputEvent->getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700533 case InputEventType::KEY: {
Jackal Guof9696682018-10-05 12:23:23 +0800534 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800535 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800536 break;
537 }
538
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700539 case InputEventType::MOTION: {
Jackal Guof9696682018-10-05 12:23:23 +0800540 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800541 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800542 break;
543 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700544 default: {
545 ADD_FAILURE() << "Should only filter keys or motions";
546 break;
547 }
Jackal Guof9696682018-10-05 12:23:23 +0800548 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549 return true;
550 }
551
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800552 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
553 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
554 // Clear intercept state when we handled the event.
555 mInterceptKeyTimeout = 0ms;
556 }
557 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800558
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600559 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800560
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600561 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800562 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
563 // Clear intercept state so we could dispatch the event in next wake.
564 mInterceptKeyTimeout = 0ms;
565 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800566 }
567
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600568 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800569 return false;
570 }
571
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600572 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
573 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700574 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800575 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
576 * essentially a passthrough for notifySwitch.
577 */
Harry Cutts33476232023-01-30 19:57:29 +0000578 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800579 }
580
Sean Stoutb4e0a592021-02-23 07:34:53 -0800581 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600583 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700584 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700585 mOnPointerDownToken = newToken;
586 }
587
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000588 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800589 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000590 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800591 mPointerCaptureChangedCondition.notify_all();
592 }
593
arthurhungf452d0b2021-01-06 00:19:52 +0800594 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
595 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800596 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800597 mDropTargetWindowToken = token;
598 }
599
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700600 void assertFilterInputEventWasCalledInternal(
601 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700602 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800603 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700604 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800605 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800606 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607};
608
Michael Wrightd02c5b62014-02-10 15:10:22 -0800609// --- InputDispatcherTest ---
610
611class InputDispatcherTest : public testing::Test {
612protected:
613 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700614 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800615
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000616 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700617 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800618 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800619 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000620 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700621 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622 }
623
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000624 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700625 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800626 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700627 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800628 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700629
630 /**
631 * Used for debugging when writing the test
632 */
633 void dumpDispatcherState() {
634 std::string dump;
635 mDispatcher->dump(dump);
636 std::stringstream ss(dump);
637 std::string to;
638
639 while (std::getline(ss, to, '\n')) {
640 ALOGE("%s", to.c_str());
641 }
642 }
Vishnu Nair958da932020-08-21 17:12:37 -0700643
Chavi Weingarten847e8512023-03-29 00:26:09 +0000644 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700645 FocusRequest request;
646 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000647 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700648 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
649 request.displayId = window->getInfo()->displayId;
650 mDispatcher->setFocusedWindow(request);
651 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652};
653
Michael Wrightd02c5b62014-02-10 15:10:22 -0800654TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
655 KeyEvent event;
656
657 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800658 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
659 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600660 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
661 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800662 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000663 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000664 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665 << "Should reject key events with undefined action.";
666
667 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800668 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
669 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600670 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800671 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000672 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000673 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800674 << "Should reject key events with ACTION_MULTIPLE.";
675}
676
677TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
678 MotionEvent event;
679 PointerProperties pointerProperties[MAX_POINTERS + 1];
680 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800681 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800682 pointerProperties[i].clear();
683 pointerProperties[i].id = i;
684 pointerCoords[i].clear();
685 }
686
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800687 // Some constants commonly used below
688 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
689 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
690 constexpr int32_t metaState = AMETA_NONE;
691 constexpr MotionClassification classification = MotionClassification::NONE;
692
chaviw9eaa22c2020-07-01 16:21:27 -0700693 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800694 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800695 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700696 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
697 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700698 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
699 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700700 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800701 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000702 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000703 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800704 << "Should reject motion events with undefined action.";
705
706 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800707 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800708 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
709 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
710 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
711 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500712 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000714 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000715 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 << "Should reject motion events with pointer down index too large.";
717
Garfield Tanfbe732e2020-01-24 11:26:14 -0800718 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700719 AMOTION_EVENT_ACTION_POINTER_DOWN |
720 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700721 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
722 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700723 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500724 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000726 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000727 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 << "Should reject motion events with pointer down index too small.";
729
730 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800731 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800732 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
733 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
734 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
735 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500736 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800737 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000738 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000739 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800740 << "Should reject motion events with pointer up index too large.";
741
Garfield Tanfbe732e2020-01-24 11:26:14 -0800742 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700743 AMOTION_EVENT_ACTION_POINTER_UP |
744 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700745 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
746 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700747 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500748 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000750 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000751 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800752 << "Should reject motion events with pointer up index too small.";
753
754 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800755 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
756 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700757 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700758 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
759 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700760 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800761 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000762 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000763 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800764 << "Should reject motion events with 0 pointers.";
765
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*/ MAX_POINTERS + 1, 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 more than MAX_POINTERS pointers.";
776
777 // Rejects motion events with invalid pointer ids.
778 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800779 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
780 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700781 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700782 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
783 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700784 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800785 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000786 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000787 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800788 << "Should reject motion events with pointer ids less than 0.";
789
790 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700796 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
801
802 // Rejects motion events with duplicate pointer ids.
803 pointerProperties[0].id = 1;
804 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800805 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
806 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700807 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700808 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
809 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700810 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800811 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000812 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000813 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800814 << "Should reject motion events with duplicate pointer ids.";
815}
816
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800817/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
818
819TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
820 constexpr nsecs_t eventTime = 20;
Harry Cutts33476232023-01-30 19:57:29 +0000821 NotifyConfigurationChangedArgs args(/*id=*/10, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800822 mDispatcher->notifyConfigurationChanged(&args);
823 ASSERT_TRUE(mDispatcher->waitForIdle());
824
825 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
826}
827
828TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000829 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
830 /*switchMask=*/2);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800831 mDispatcher->notifySwitch(&args);
832
833 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
834 args.policyFlags |= POLICY_FLAG_TRUSTED;
835 mFakePolicy->assertNotifySwitchWasCalled(args);
836}
837
Arthur Hungb92218b2018-08-14 12:00:21 +0800838// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700839static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700840// Default input dispatching timeout if there is no focused application or paused window
841// from which to determine an appropriate dispatching timeout.
842static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
843 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
844 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800845
846class FakeApplicationHandle : public InputApplicationHandle {
847public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700848 FakeApplicationHandle() {
849 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700850 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500851 mInfo.dispatchingTimeoutMillis =
852 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700853 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800854 virtual ~FakeApplicationHandle() {}
855
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000856 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700857
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500858 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
859 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700860 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800861};
862
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800863class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800864public:
Garfield Tan15601662020-09-22 15:32:38 -0700865 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800866 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700867 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800868 }
869
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800870 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700871 InputEvent* event;
872 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
873 if (!consumeSeq) {
874 return nullptr;
875 }
876 finishEvent(*consumeSeq);
877 return event;
878 }
879
880 /**
881 * Receive an event without acknowledging it.
882 * Return the sequence number that could later be used to send finished signal.
883 */
884 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800885 uint32_t consumeSeq;
886 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800887
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800888 std::chrono::time_point start = std::chrono::steady_clock::now();
889 status_t status = WOULD_BLOCK;
890 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000891 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800892 &event);
893 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
894 if (elapsed > 100ms) {
895 break;
896 }
897 }
898
899 if (status == WOULD_BLOCK) {
900 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700901 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 }
903
904 if (status != OK) {
905 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700906 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800907 }
908 if (event == nullptr) {
909 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800911 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700912 if (outEvent != nullptr) {
913 *outEvent = event;
914 }
915 return consumeSeq;
916 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800917
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700918 /**
919 * To be used together with "receiveEvent" to complete the consumption of an event.
920 */
921 void finishEvent(uint32_t consumeSeq) {
922 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
923 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 }
925
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000926 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
927 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
928 ASSERT_EQ(OK, status);
929 }
930
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700931 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000932 std::optional<int32_t> expectedDisplayId,
933 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800934 InputEvent* event = consume();
935
936 ASSERT_NE(nullptr, event) << mName.c_str()
937 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800938 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700939 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
940 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800941
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000942 if (expectedDisplayId.has_value()) {
943 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
944 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800945
Tiger Huang8664f8c2018-10-11 19:14:35 +0800946 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700947 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800948 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
949 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000950 if (expectedFlags.has_value()) {
951 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
952 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800953 break;
954 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700955 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800956 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000957 assertMotionAction(expectedAction, motionEvent.getAction());
958
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000959 if (expectedFlags.has_value()) {
960 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
961 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800962 break;
963 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100965 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
966 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700967 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800968 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
969 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700970 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000971 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
972 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800974 FAIL() << "Use 'consumeDragEvent' for DRAG events";
975 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800976 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800977 }
978
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800979 MotionEvent* consumeMotion() {
980 InputEvent* event = consume();
981
982 if (event == nullptr) {
983 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
984 return nullptr;
985 }
986
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700987 if (event->getType() != InputEventType::MOTION) {
988 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800989 return nullptr;
990 }
991 return static_cast<MotionEvent*>(event);
992 }
993
994 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
995 MotionEvent* motionEvent = consumeMotion();
996 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
997 ASSERT_THAT(*motionEvent, matcher);
998 }
999
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1001 InputEvent* event = consume();
1002 ASSERT_NE(nullptr, event) << mName.c_str()
1003 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1005 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006
1007 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1008 << mName.c_str() << ": event displayId should always be NONE.";
1009
1010 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1011 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001012 }
1013
Prabir Pradhan99987712020-11-10 18:43:05 -08001014 void consumeCaptureEvent(bool hasCapture) {
1015 const InputEvent* event = consume();
1016 ASSERT_NE(nullptr, event) << mName.c_str()
1017 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001018 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1019 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001020
1021 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1022 << mName.c_str() << ": event displayId should always be NONE.";
1023
1024 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1025 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1026 }
1027
arthurhungb89ccb02020-12-30 16:19:01 +08001028 void consumeDragEvent(bool isExiting, float x, float y) {
1029 const InputEvent* event = consume();
1030 ASSERT_NE(nullptr, event) << mName.c_str()
1031 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001032 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001033
1034 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036
1037 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1038 EXPECT_EQ(isExiting, dragEvent.isExiting());
1039 EXPECT_EQ(x, dragEvent.getX());
1040 EXPECT_EQ(y, dragEvent.getY());
1041 }
1042
Antonio Kantekf16f2832021-09-28 04:39:20 +00001043 void consumeTouchModeEvent(bool inTouchMode) {
1044 const InputEvent* event = consume();
1045 ASSERT_NE(nullptr, event) << mName.c_str()
1046 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001047 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1048 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001049
1050 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1051 << mName.c_str() << ": event displayId should always be NONE.";
1052 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1053 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1054 }
1055
chaviwd1c23182019-12-20 18:44:56 -08001056 void assertNoEvents() {
1057 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001058 if (event == nullptr) {
1059 return;
1060 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001061 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1063 ADD_FAILURE() << "Received key event "
1064 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001066 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1067 ADD_FAILURE() << "Received motion event "
1068 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001070 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1071 ADD_FAILURE() << "Received focus event, hasFocus = "
1072 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001074 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1075 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1076 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001077 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001078 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1079 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1080 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001081 }
1082 FAIL() << mName.c_str()
1083 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001084 }
1085
1086 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1087
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001088 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1089
chaviwd1c23182019-12-20 18:44:56 -08001090protected:
1091 std::unique_ptr<InputConsumer> mConsumer;
1092 PreallocatedInputEventFactory mEventFactory;
1093
1094 std::string mName;
1095};
1096
chaviw3277faf2021-05-19 16:45:23 -05001097class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001098public:
1099 static const int32_t WIDTH = 600;
1100 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001101
Chris Yea209fde2020-07-22 13:54:51 -07001102 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001103 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001104 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001105 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001106 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001107 base::Result<std::unique_ptr<InputChannel>> channel =
1108 dispatcher->createInputChannel(name);
1109 token = (*channel)->getConnectionToken();
1110 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001111 }
1112
1113 inputApplicationHandle->updateInfo();
1114 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1115
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001116 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001117 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001118 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001119 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001120 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001121 mInfo.frameLeft = 0;
1122 mInfo.frameTop = 0;
1123 mInfo.frameRight = WIDTH;
1124 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001125 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001126 mInfo.globalScaleFactor = 1.0;
1127 mInfo.touchableRegion.clear();
1128 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001129 mInfo.ownerPid = WINDOW_PID;
1130 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001132 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001133 }
1134
Arthur Hungabbb9d82021-09-01 14:52:30 +00001135 sp<FakeWindowHandle> clone(
1136 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001137 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001138 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001139 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1140 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001141 return handle;
1142 }
1143
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001144 void setTouchable(bool touchable) {
1145 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1146 }
chaviwd1c23182019-12-20 18:44:56 -08001147
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001148 void setFocusable(bool focusable) {
1149 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1150 }
1151
1152 void setVisible(bool visible) {
1153 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1154 }
Vishnu Nair958da932020-08-21 17:12:37 -07001155
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001156 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001157 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001158 }
1159
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001160 void setPaused(bool paused) {
1161 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1162 }
1163
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001164 void setPreventSplitting(bool preventSplitting) {
1165 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001166 }
1167
1168 void setSlippery(bool slippery) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1170 }
1171
1172 void setWatchOutsideTouch(bool watchOutside) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1174 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001175
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001176 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1177
1178 void setInterceptsStylus(bool interceptsStylus) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1180 }
1181
1182 void setDropInput(bool dropInput) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1184 }
1185
1186 void setDropInputIfObscured(bool dropInputIfObscured) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1188 }
1189
1190 void setNoInputChannel(bool noInputChannel) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1192 }
1193
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001194 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1195
chaviw3277faf2021-05-19 16:45:23 -05001196 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001197
Bernardo Rufino7393d172021-02-26 13:56:11 +00001198 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1199
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001200 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001201 mInfo.frameLeft = frame.left;
1202 mInfo.frameTop = frame.top;
1203 mInfo.frameRight = frame.right;
1204 mInfo.frameBottom = frame.bottom;
1205 mInfo.touchableRegion.clear();
1206 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001207
1208 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1209 ui::Transform translate;
1210 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1211 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001212 }
1213
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001214 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1215
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 void setIsWallpaper(bool isWallpaper) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1218 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001219
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001220 void setDupTouchToWallpaper(bool hasWallpaper) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1222 }
chaviwd1c23182019-12-20 18:44:56 -08001223
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001224 void setTrustedOverlay(bool trustedOverlay) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1226 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001227
chaviw9eaa22c2020-07-01 16:21:27 -07001228 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1229 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1230 }
1231
1232 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001233
yunho.shinf4a80b82020-11-16 21:13:57 +09001234 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1235
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001236 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001237 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001238 }
1239
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001240 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001241 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001242 }
1243
Svet Ganov5d3bc372020-01-26 23:11:07 -08001244 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001245 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001246 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1247 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001248 }
1249
1250 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001251 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001252 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1253 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001254 }
1255
1256 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001257 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001258 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1259 }
1260
1261 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1262 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001263 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001264 expectedFlags);
1265 }
1266
Svet Ganov5d3bc372020-01-26 23:11:07 -08001267 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1269 int32_t expectedFlags = 0) {
1270 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1271 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001272 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001273 }
1274
1275 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 int32_t expectedFlags = 0) {
1277 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1278 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001279 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 }
1281
1282 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001283 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001284 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001285 expectedFlags);
1286 }
1287
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001288 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1289 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001290 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001291 expectedFlags);
1292 }
1293
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001294 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1295 int32_t expectedFlags = 0) {
1296 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001297 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001298 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001299 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1300 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1301 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1302 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1303 }
1304
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001305 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1306 ASSERT_NE(mInputReceiver, nullptr)
1307 << "Cannot consume events from a window with no receiver";
1308 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1309 }
1310
Prabir Pradhan99987712020-11-10 18:43:05 -08001311 void consumeCaptureEvent(bool hasCapture) {
1312 ASSERT_NE(mInputReceiver, nullptr)
1313 << "Cannot consume events from a window with no receiver";
1314 mInputReceiver->consumeCaptureEvent(hasCapture);
1315 }
1316
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001317 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1318 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001319 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001320 ASSERT_THAT(*motionEvent, matcher);
1321 }
1322
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001323 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001324 std::optional<int32_t> expectedDisplayId,
1325 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001326 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1327 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1328 expectedFlags);
1329 }
1330
arthurhungb89ccb02020-12-30 16:19:01 +08001331 void consumeDragEvent(bool isExiting, float x, float y) {
1332 mInputReceiver->consumeDragEvent(isExiting, x, y);
1333 }
1334
Antonio Kantekf16f2832021-09-28 04:39:20 +00001335 void consumeTouchModeEvent(bool inTouchMode) {
1336 ASSERT_NE(mInputReceiver, nullptr)
1337 << "Cannot consume events from a window with no receiver";
1338 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1339 }
1340
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001341 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001342 if (mInputReceiver == nullptr) {
1343 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1344 return std::nullopt;
1345 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001346 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001347 }
1348
1349 void finishEvent(uint32_t sequenceNum) {
1350 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1351 mInputReceiver->finishEvent(sequenceNum);
1352 }
1353
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001354 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1355 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1356 mInputReceiver->sendTimeline(inputEventId, timeline);
1357 }
1358
chaviwaf87b3e2019-10-01 16:59:28 -07001359 InputEvent* consume() {
1360 if (mInputReceiver == nullptr) {
1361 return nullptr;
1362 }
1363 return mInputReceiver->consume();
1364 }
1365
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001366 MotionEvent* consumeMotion() {
1367 InputEvent* event = consume();
1368 if (event == nullptr) {
1369 ADD_FAILURE() << "Consume failed : no event";
1370 return nullptr;
1371 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001372 if (event->getType() != InputEventType::MOTION) {
1373 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 return nullptr;
1375 }
1376 return static_cast<MotionEvent*>(event);
1377 }
1378
Arthur Hungb92218b2018-08-14 12:00:21 +08001379 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001380 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001381 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001382 return; // Can't receive events if the window does not have input channel
1383 }
1384 ASSERT_NE(nullptr, mInputReceiver)
1385 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001386 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001387 }
1388
chaviwaf87b3e2019-10-01 16:59:28 -07001389 sp<IBinder> getToken() { return mInfo.token; }
1390
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001391 const std::string& getName() { return mName; }
1392
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001393 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1394 mInfo.ownerPid = ownerPid;
1395 mInfo.ownerUid = ownerUid;
1396 }
1397
Prabir Pradhanedd96402022-02-15 01:46:16 -08001398 int32_t getPid() const { return mInfo.ownerPid; }
1399
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001400 void destroyReceiver() { mInputReceiver = nullptr; }
1401
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001402 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1403
chaviwd1c23182019-12-20 18:44:56 -08001404private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001405 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001406 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001407 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001408};
1409
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001410std::atomic<int32_t> FakeWindowHandle::sId{1};
1411
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001412static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001413 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001414 int32_t displayId = ADISPLAY_ID_NONE,
1415 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001416 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001417 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1418 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001419 KeyEvent event;
1420 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1421
1422 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001423 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001424 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1425 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001426
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001427 if (!allowKeyRepeat) {
1428 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1429 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001430 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001431 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001432}
1433
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001434static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001435 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001436 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001437}
1438
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001439// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1440// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1441// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001442static InputEventInjectionResult injectKeyDownNoRepeat(
1443 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001444 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001445 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001446 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001447}
1448
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001449static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001451 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001452}
1453
Garfield Tandf26e862020-07-01 20:18:19 -07001454class PointerBuilder {
1455public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001456 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001457 mProperties.clear();
1458 mProperties.id = id;
1459 mProperties.toolType = toolType;
1460 mCoords.clear();
1461 }
1462
1463 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1464
1465 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1466
1467 PointerBuilder& axis(int32_t axis, float value) {
1468 mCoords.setAxisValue(axis, value);
1469 return *this;
1470 }
1471
1472 PointerProperties buildProperties() const { return mProperties; }
1473
1474 PointerCoords buildCoords() const { return mCoords; }
1475
1476private:
1477 PointerProperties mProperties;
1478 PointerCoords mCoords;
1479};
1480
1481class MotionEventBuilder {
1482public:
1483 MotionEventBuilder(int32_t action, int32_t source) {
1484 mAction = action;
1485 mSource = source;
1486 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001487 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001488 }
1489
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001490 MotionEventBuilder& deviceId(int32_t deviceId) {
1491 mDeviceId = deviceId;
1492 return *this;
1493 }
1494
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001495 MotionEventBuilder& downTime(nsecs_t downTime) {
1496 mDownTime = downTime;
1497 return *this;
1498 }
1499
Garfield Tandf26e862020-07-01 20:18:19 -07001500 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1501 mEventTime = eventTime;
1502 return *this;
1503 }
1504
1505 MotionEventBuilder& displayId(int32_t displayId) {
1506 mDisplayId = displayId;
1507 return *this;
1508 }
1509
1510 MotionEventBuilder& actionButton(int32_t actionButton) {
1511 mActionButton = actionButton;
1512 return *this;
1513 }
1514
arthurhung6d4bed92021-03-17 11:59:33 +08001515 MotionEventBuilder& buttonState(int32_t buttonState) {
1516 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001517 return *this;
1518 }
1519
1520 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1521 mRawXCursorPosition = rawXCursorPosition;
1522 return *this;
1523 }
1524
1525 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1526 mRawYCursorPosition = rawYCursorPosition;
1527 return *this;
1528 }
1529
1530 MotionEventBuilder& pointer(PointerBuilder pointer) {
1531 mPointers.push_back(pointer);
1532 return *this;
1533 }
1534
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001535 MotionEventBuilder& addFlag(uint32_t flags) {
1536 mFlags |= flags;
1537 return *this;
1538 }
1539
Garfield Tandf26e862020-07-01 20:18:19 -07001540 MotionEvent build() {
1541 std::vector<PointerProperties> pointerProperties;
1542 std::vector<PointerCoords> pointerCoords;
1543 for (const PointerBuilder& pointer : mPointers) {
1544 pointerProperties.push_back(pointer.buildProperties());
1545 pointerCoords.push_back(pointer.buildCoords());
1546 }
1547
1548 // Set mouse cursor position for the most common cases to avoid boilerplate.
1549 if (mSource == AINPUT_SOURCE_MOUSE &&
1550 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1551 mPointers.size() == 1) {
1552 mRawXCursorPosition = pointerCoords[0].getX();
1553 mRawYCursorPosition = pointerCoords[0].getY();
1554 }
1555
1556 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001557 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001558 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001559 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001560 mButtonState, MotionClassification::NONE, identityTransform,
1561 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001562 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001563 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001564
1565 return event;
1566 }
1567
1568private:
1569 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001570 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001571 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001572 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001573 nsecs_t mEventTime;
1574 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1575 int32_t mActionButton{0};
1576 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001577 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001578 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1579 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1580
1581 std::vector<PointerBuilder> mPointers;
1582};
1583
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001584class MotionArgsBuilder {
1585public:
1586 MotionArgsBuilder(int32_t action, int32_t source) {
1587 mAction = action;
1588 mSource = source;
1589 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1590 mDownTime = mEventTime;
1591 }
1592
1593 MotionArgsBuilder& deviceId(int32_t deviceId) {
1594 mDeviceId = deviceId;
1595 return *this;
1596 }
1597
1598 MotionArgsBuilder& downTime(nsecs_t downTime) {
1599 mDownTime = downTime;
1600 return *this;
1601 }
1602
1603 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1604 mEventTime = eventTime;
1605 return *this;
1606 }
1607
1608 MotionArgsBuilder& displayId(int32_t displayId) {
1609 mDisplayId = displayId;
1610 return *this;
1611 }
1612
1613 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1614 mPolicyFlags = policyFlags;
1615 return *this;
1616 }
1617
1618 MotionArgsBuilder& actionButton(int32_t actionButton) {
1619 mActionButton = actionButton;
1620 return *this;
1621 }
1622
1623 MotionArgsBuilder& buttonState(int32_t buttonState) {
1624 mButtonState = buttonState;
1625 return *this;
1626 }
1627
1628 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1629 mRawXCursorPosition = rawXCursorPosition;
1630 return *this;
1631 }
1632
1633 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1634 mRawYCursorPosition = rawYCursorPosition;
1635 return *this;
1636 }
1637
1638 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1639 mPointers.push_back(pointer);
1640 return *this;
1641 }
1642
1643 MotionArgsBuilder& addFlag(uint32_t flags) {
1644 mFlags |= flags;
1645 return *this;
1646 }
1647
1648 NotifyMotionArgs build() {
1649 std::vector<PointerProperties> pointerProperties;
1650 std::vector<PointerCoords> pointerCoords;
1651 for (const PointerBuilder& pointer : mPointers) {
1652 pointerProperties.push_back(pointer.buildProperties());
1653 pointerCoords.push_back(pointer.buildCoords());
1654 }
1655
1656 // Set mouse cursor position for the most common cases to avoid boilerplate.
1657 if (mSource == AINPUT_SOURCE_MOUSE &&
1658 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1659 mPointers.size() == 1) {
1660 mRawXCursorPosition = pointerCoords[0].getX();
1661 mRawYCursorPosition = pointerCoords[0].getY();
1662 }
1663
1664 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1665 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1666 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1667 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1668 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1669 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1670
1671 return args;
1672 }
1673
1674private:
1675 int32_t mAction;
1676 int32_t mDeviceId = DEVICE_ID;
1677 int32_t mSource;
1678 nsecs_t mDownTime;
1679 nsecs_t mEventTime;
1680 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1681 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1682 int32_t mActionButton{0};
1683 int32_t mButtonState{0};
1684 int32_t mFlags{0};
1685 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1686 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1687
1688 std::vector<PointerBuilder> mPointers;
1689};
1690
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001691static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001692 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001693 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001694 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1695 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1696 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1697 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001698}
1699
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001700static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001701 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001702 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001703 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001704 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1705 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001706 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001707 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1708 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001709 MotionEvent event = MotionEventBuilder(action, source)
1710 .displayId(displayId)
1711 .eventTime(eventTime)
1712 .rawXCursorPosition(cursorPosition.x)
1713 .rawYCursorPosition(cursorPosition.y)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001714 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001715 .x(position.x)
1716 .y(position.y))
1717 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001718
1719 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001720 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1721 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001722}
1723
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001724static InputEventInjectionResult injectMotionDown(
1725 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1726 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001727 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001728}
1729
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001730static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001731 int32_t source, int32_t displayId,
1732 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001733 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001734}
1735
Jackal Guof9696682018-10-05 12:23:23 +08001736static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1737 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1738 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001739 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001740 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1741 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001742
1743 return args;
1744}
1745
chaviwd1c23182019-12-20 18:44:56 -08001746static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1747 const std::vector<PointF>& points) {
1748 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001749 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1750 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1751 }
1752
chaviwd1c23182019-12-20 18:44:56 -08001753 PointerProperties pointerProperties[pointerCount];
1754 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001755
chaviwd1c23182019-12-20 18:44:56 -08001756 for (size_t i = 0; i < pointerCount; i++) {
1757 pointerProperties[i].clear();
1758 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001759 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001760
chaviwd1c23182019-12-20 18:44:56 -08001761 pointerCoords[i].clear();
1762 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1763 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1764 }
Jackal Guof9696682018-10-05 12:23:23 +08001765
1766 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1767 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001768 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001769 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1770 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001771 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1772 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001773 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1774 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001775
1776 return args;
1777}
1778
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001779static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1780 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1781}
1782
chaviwd1c23182019-12-20 18:44:56 -08001783static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1784 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1785}
1786
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001787static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1788 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001789 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001790}
1791
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001792/**
1793 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1794 * broken channel.
1795 */
1796TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1798 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001799 sp<FakeWindowHandle>::make(application, mDispatcher,
1800 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001801
1802 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1803
1804 // Window closes its channel, but the window remains.
1805 window->destroyReceiver();
1806 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1807}
1808
Arthur Hungb92218b2018-08-14 12:00:21 +08001809TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1812 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001813
Arthur Hung72d8dc32020-03-28 00:48:39 +00001814 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1816 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001818
1819 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001820 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001821}
1822
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001823TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1824 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001825 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1826 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001827
1828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1829 // Inject a MotionEvent to an unknown display.
1830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1831 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1833
1834 // Window should receive motion event.
1835 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1836}
1837
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001838/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001839 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001840 * This test serves as a sanity check for the next test, where setInputWindows is
1841 * called twice.
1842 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001843TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001845 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1846 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001847 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001848
1849 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001851 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1852 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001854
1855 // Window should receive motion event.
1856 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1857}
1858
1859/**
1860 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001861 */
1862TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001863 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001864 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1865 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001866 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001867
1868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1869 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001871 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1872 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001874
1875 // Window should receive motion event.
1876 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1877}
1878
Arthur Hungb92218b2018-08-14 12:00:21 +08001879// The foreground window should receive the first touch down event.
1880TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001882 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001883 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001884 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001885 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001886
Arthur Hung72d8dc32020-03-28 00:48:39 +00001887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1889 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001891
1892 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001893 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001894 windowSecond->assertNoEvents();
1895}
1896
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897/**
1898 * Two windows: A top window, and a wallpaper behind the window.
1899 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1900 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001901 * 1. foregroundWindow <-- dup touch to wallpaper
1902 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001903 */
1904TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1906 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001907 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001908 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001909 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001910 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001911 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912
1913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1916 {100, 200}))
1917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1918
1919 // Both foreground window and its wallpaper should receive the touch down
1920 foregroundWindow->consumeMotionDown();
1921 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1922
1923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1924 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1925 ADISPLAY_ID_DEFAULT, {110, 200}))
1926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1927
1928 foregroundWindow->consumeMotionMove();
1929 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1930
1931 // Now the foreground window goes away, but the wallpaper stays
1932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1933 foregroundWindow->consumeMotionCancel();
1934 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1935 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1936}
1937
1938/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001939 * Two fingers down on the window, and lift off the first finger.
1940 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1941 * contains a single pointer.
1942 */
1943TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1945 sp<FakeWindowHandle> window =
1946 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1947
1948 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1949 NotifyMotionArgs args;
1950 // First touch pointer down on right window
1951 mDispatcher->notifyMotion(&(
1952 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001953 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001954 .build()));
1955 // Second touch pointer down
1956 mDispatcher->notifyMotion(&(
1957 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1958
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001959 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1960 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001961 .build()));
1962 // First touch pointer lifts. The second one remains down
1963 mDispatcher->notifyMotion(&(
1964 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1965
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001966 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1967 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001968 .build()));
1969 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1970 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1971 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1972
1973 // Remove the window. The gesture should be canceled
1974 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1975 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1976 window->consumeMotionEvent(
1977 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1978}
1979
1980/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001981 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1982 * with the following differences:
1983 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1984 * clean up the connection.
1985 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1986 * Ensure that there's no crash in the dispatcher.
1987 */
1988TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1990 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001991 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001992 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001993 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001994 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001995 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001996
1997 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1999 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2000 {100, 200}))
2001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2002
2003 // Both foreground window and its wallpaper should receive the touch down
2004 foregroundWindow->consumeMotionDown();
2005 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2006
2007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2008 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2009 ADISPLAY_ID_DEFAULT, {110, 200}))
2010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2011
2012 foregroundWindow->consumeMotionMove();
2013 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2014
2015 // Wallpaper closes its channel, but the window remains.
2016 wallpaperWindow->destroyReceiver();
2017 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2018
2019 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2020 // is no longer valid.
2021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2022 foregroundWindow->consumeMotionCancel();
2023}
2024
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025class ShouldSplitTouchFixture : public InputDispatcherTest,
2026 public ::testing::WithParamInterface<bool> {};
2027INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2028 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002029/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 * A single window that receives touch (on top), and a wallpaper window underneath it.
2031 * The top window gets a multitouch gesture.
2032 * Ensure that wallpaper gets the same gesture.
2033 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002034TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002036 sp<FakeWindowHandle> foregroundWindow =
2037 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2038 foregroundWindow->setDupTouchToWallpaper(true);
2039 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040
2041 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002042 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002043 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046
2047 // Touch down on top window
2048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2050 {100, 100}))
2051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2052
2053 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
2057 // Second finger down on the top window
2058 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002059 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002060 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002061 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2062 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002063 .build();
2064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2065 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2066 InputEventInjectionSync::WAIT_FOR_RESULT))
2067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2068
Harry Cutts33476232023-01-30 19:57:29 +00002069 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2070 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002071 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002072
2073 const MotionEvent secondFingerUpEvent =
2074 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2075 .displayId(ADISPLAY_ID_DEFAULT)
2076 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002077 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2078 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002079 .build();
2080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2081 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2082 InputEventInjectionSync::WAIT_FOR_RESULT))
2083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2084 foregroundWindow->consumeMotionPointerUp(0);
2085 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2086
2087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002088 injectMotionEvent(mDispatcher,
2089 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2090 AINPUT_SOURCE_TOUCHSCREEN)
2091 .displayId(ADISPLAY_ID_DEFAULT)
2092 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2093 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002094 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002095 .x(100)
2096 .y(100))
2097 .build(),
2098 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002099 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2100 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2101 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102}
2103
2104/**
2105 * Two windows: a window on the left and window on the right.
2106 * A third window, wallpaper, is behind both windows, and spans both top windows.
2107 * The first touch down goes to the left window. A second pointer touches down on the right window.
2108 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2109 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2110 * ACTION_POINTER_DOWN(1).
2111 */
2112TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2114 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002115 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002116 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002117 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002118
2119 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002120 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002121 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002122 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002123
2124 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002125 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002126 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002127 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002128
2129 mDispatcher->setInputWindows(
2130 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2131
2132 // Touch down on left window
2133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2134 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2135 {100, 100}))
2136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2137
2138 // Both foreground window and its wallpaper should receive the touch down
2139 leftWindow->consumeMotionDown();
2140 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2141
2142 // Second finger down on the right window
2143 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002144 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002145 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002146 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2147 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002148 .build();
2149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2150 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2151 InputEventInjectionSync::WAIT_FOR_RESULT))
2152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2153
2154 leftWindow->consumeMotionMove();
2155 // Since the touch is split, right window gets ACTION_DOWN
2156 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002157 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002158 expectedWallpaperFlags);
2159
2160 // Now, leftWindow, which received the first finger, disappears.
2161 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2162 leftWindow->consumeMotionCancel();
2163 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2164 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2165
2166 // The pointer that's still down on the right window moves, and goes to the right window only.
2167 // As far as the dispatcher's concerned though, both pointers are still present.
2168 const MotionEvent secondFingerMoveEvent =
2169 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2170 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002171 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2172 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002173 .build();
2174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2175 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2176 InputEventInjectionSync::WAIT_FOR_RESULT));
2177 rightWindow->consumeMotionMove();
2178
2179 leftWindow->assertNoEvents();
2180 rightWindow->assertNoEvents();
2181 wallpaperWindow->assertNoEvents();
2182}
2183
Arthur Hungc539dbb2022-12-08 07:45:36 +00002184/**
2185 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2186 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2187 * The right window should receive ACTION_DOWN.
2188 */
2189TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002191 sp<FakeWindowHandle> leftWindow =
2192 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2193 leftWindow->setFrame(Rect(0, 0, 200, 200));
2194 leftWindow->setDupTouchToWallpaper(true);
2195 leftWindow->setSlippery(true);
2196
2197 sp<FakeWindowHandle> rightWindow =
2198 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2199 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002200
2201 sp<FakeWindowHandle> wallpaperWindow =
2202 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2203 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002204
Arthur Hungc539dbb2022-12-08 07:45:36 +00002205 mDispatcher->setInputWindows(
2206 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002207
Arthur Hungc539dbb2022-12-08 07:45:36 +00002208 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2210 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002211 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002212 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002213
2214 // Both foreground window and its wallpaper should receive the touch down
2215 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002216 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2217
Arthur Hungc539dbb2022-12-08 07:45:36 +00002218 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002220 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2221 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2223
Arthur Hungc539dbb2022-12-08 07:45:36 +00002224 leftWindow->consumeMotionCancel();
2225 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2226 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002227}
2228
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002229/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002230 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2231 * interactive, it might stop sending this flag.
2232 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2233 * to have a consistent input stream.
2234 *
2235 * Test procedure:
2236 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2237 * DOWN (new gesture).
2238 *
2239 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2240 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2241 *
2242 * We technically just need a single window here, but we are using two windows (spy on top and a
2243 * regular window below) to emulate the actual situation where it happens on the device.
2244 */
2245TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2247 sp<FakeWindowHandle> spyWindow =
2248 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2249 spyWindow->setFrame(Rect(0, 0, 200, 200));
2250 spyWindow->setTrustedOverlay(true);
2251 spyWindow->setSpy(true);
2252
2253 sp<FakeWindowHandle> window =
2254 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2255 window->setFrame(Rect(0, 0, 200, 200));
2256
2257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2258 const int32_t touchDeviceId = 4;
2259 NotifyMotionArgs args;
2260
2261 // Two pointers down
2262 mDispatcher->notifyMotion(&(
2263 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2264 .deviceId(touchDeviceId)
2265 .policyFlags(DEFAULT_POLICY_FLAGS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002266 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002267 .build()));
2268
2269 mDispatcher->notifyMotion(&(
2270 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2271 .deviceId(touchDeviceId)
2272 .policyFlags(DEFAULT_POLICY_FLAGS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002273 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2274 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002275 .build()));
2276 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2277 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2278 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2279 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2280
2281 // Cancel the current gesture. Send the cancel without the default policy flags.
2282 mDispatcher->notifyMotion(&(
2283 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2284 .deviceId(touchDeviceId)
2285 .policyFlags(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002286 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2287 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002288 .build()));
2289 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2290 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2291
2292 // We don't need to reset the device to reproduce the issue, but the reset event typically
2293 // follows, so we keep it here to model the actual listener behaviour more closely.
2294 NotifyDeviceResetArgs resetArgs;
2295 resetArgs.id = 1; // arbitrary id
2296 resetArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2297 resetArgs.deviceId = touchDeviceId;
2298 mDispatcher->notifyDeviceReset(&resetArgs);
2299
2300 // Start new gesture
2301 mDispatcher->notifyMotion(&(
2302 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2303 .deviceId(touchDeviceId)
2304 .policyFlags(DEFAULT_POLICY_FLAGS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002305 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002306 .build()));
2307 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2308 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2309
2310 // No more events
2311 spyWindow->assertNoEvents();
2312 window->assertNoEvents();
2313}
2314
2315/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002316 * Two windows: a window on the left and a window on the right.
2317 * Mouse is hovered from the right window into the left window.
2318 * Next, we tap on the left window, where the cursor was last seen.
2319 * The second tap is done onto the right window.
2320 * The mouse and tap are from two different devices.
2321 * We technically don't need to set the downtime / eventtime for these events, but setting these
2322 * explicitly helps during debugging.
2323 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2324 * In the buggy implementation, a tap on the right window would cause a crash.
2325 */
2326TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2328 sp<FakeWindowHandle> leftWindow =
2329 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2330 leftWindow->setFrame(Rect(0, 0, 200, 200));
2331
2332 sp<FakeWindowHandle> rightWindow =
2333 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2334 rightWindow->setFrame(Rect(200, 0, 400, 200));
2335
2336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2337 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2338 // stale.
2339 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2340 const int32_t mouseDeviceId = 6;
2341 const int32_t touchDeviceId = 4;
2342 // Move the cursor from right
2343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2344 injectMotionEvent(mDispatcher,
2345 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2346 AINPUT_SOURCE_MOUSE)
2347 .deviceId(mouseDeviceId)
2348 .downTime(baseTime + 10)
2349 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002350 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002351 .x(300)
2352 .y(100))
2353 .build()));
2354 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2355
2356 // .. to the left window
2357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2358 injectMotionEvent(mDispatcher,
2359 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2360 AINPUT_SOURCE_MOUSE)
2361 .deviceId(mouseDeviceId)
2362 .downTime(baseTime + 10)
2363 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002364 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002365 .x(110)
2366 .y(100))
2367 .build()));
2368 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2369 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2370 // Now tap the left window
2371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2372 injectMotionEvent(mDispatcher,
2373 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2374 AINPUT_SOURCE_TOUCHSCREEN)
2375 .deviceId(touchDeviceId)
2376 .downTime(baseTime + 40)
2377 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002378 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002379 .x(100)
2380 .y(100))
2381 .build()));
2382 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2383 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2384
2385 // release tap
2386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2387 injectMotionEvent(mDispatcher,
2388 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2389 AINPUT_SOURCE_TOUCHSCREEN)
2390 .deviceId(touchDeviceId)
2391 .downTime(baseTime + 40)
2392 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002393 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002394 .x(100)
2395 .y(100))
2396 .build()));
2397 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2398
2399 // Tap the window on the right
2400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2401 injectMotionEvent(mDispatcher,
2402 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2403 AINPUT_SOURCE_TOUCHSCREEN)
2404 .deviceId(touchDeviceId)
2405 .downTime(baseTime + 60)
2406 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002407 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002408 .x(300)
2409 .y(100))
2410 .build()));
2411 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2412
2413 // release tap
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2415 injectMotionEvent(mDispatcher,
2416 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 60)
2420 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002421 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002422 .x(300)
2423 .y(100))
2424 .build()));
2425 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2426
2427 // No more events
2428 leftWindow->assertNoEvents();
2429 rightWindow->assertNoEvents();
2430}
2431
2432/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002433 * Two windows: a window on the left and a window on the right.
2434 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2435 * down. Then, on the left window, also place second touch pointer down.
2436 * This test tries to reproduce a crash.
2437 * In the buggy implementation, second pointer down on the left window would cause a crash.
2438 */
2439TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2441 sp<FakeWindowHandle> leftWindow =
2442 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2443 leftWindow->setFrame(Rect(0, 0, 200, 200));
2444
2445 sp<FakeWindowHandle> rightWindow =
2446 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2447 rightWindow->setFrame(Rect(200, 0, 400, 200));
2448
2449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2450
2451 const int32_t touchDeviceId = 4;
2452 const int32_t mouseDeviceId = 6;
2453 NotifyMotionArgs args;
2454
2455 // Start hovering over the left window
2456 mDispatcher->notifyMotion(&(
2457 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2458 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002459 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002460 .build()));
2461 leftWindow->consumeMotionEvent(
2462 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2463
2464 // Mouse down on left window
2465 mDispatcher->notifyMotion(&(
2466 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2467 .deviceId(mouseDeviceId)
2468 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002469 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002470 .build()));
2471
2472 leftWindow->consumeMotionEvent(
2473 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2474 leftWindow->consumeMotionEvent(
2475 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2476
2477 mDispatcher->notifyMotion(&(
2478 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2479 .deviceId(mouseDeviceId)
2480 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2481 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002482 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002483 .build()));
2484 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2485
2486 // First touch pointer down on right window
2487 mDispatcher->notifyMotion(&(
2488 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2489 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002490 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002491 .build()));
2492 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2493
2494 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2495
2496 // Second touch pointer down on left window
2497 mDispatcher->notifyMotion(&(
2498 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2499 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002500 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2501 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002502 .build()));
2503 leftWindow->consumeMotionEvent(
2504 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2505 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2506 // current implementation.
2507 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2508 rightWindow->consumeMotionEvent(
2509 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2510
2511 leftWindow->assertNoEvents();
2512 rightWindow->assertNoEvents();
2513}
2514
2515/**
2516 * On a single window, use two different devices: mouse and touch.
2517 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2518 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2519 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2520 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2521 * represent a new gesture.
2522 */
2523TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2525 sp<FakeWindowHandle> window =
2526 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2527 window->setFrame(Rect(0, 0, 400, 400));
2528
2529 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2530
2531 const int32_t touchDeviceId = 4;
2532 const int32_t mouseDeviceId = 6;
2533 NotifyMotionArgs args;
2534
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002535 // First touch pointer down
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002536 mDispatcher->notifyMotion(&(
2537 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2538 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002539 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002540 .build()));
2541 // Second touch pointer down
2542 mDispatcher->notifyMotion(&(
2543 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2544 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002545 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2546 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002547 .build()));
2548 // First touch pointer lifts. The second one remains down
2549 mDispatcher->notifyMotion(&(
2550 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2551 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002552 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2553 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002554 .build()));
2555 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2556 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2557 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2558
2559 // Mouse down. The touch should be canceled
2560 mDispatcher->notifyMotion(&(
2561 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2562 .deviceId(mouseDeviceId)
2563 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002564 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002565 .build()));
2566
2567 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002568 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2570
2571 mDispatcher->notifyMotion(&(
2572 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2573 .deviceId(mouseDeviceId)
2574 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2575 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002576 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577 .build()));
2578 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2579
2580 // Second touch pointer down.
2581 mDispatcher->notifyMotion(&(
2582 args = MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2583 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002584 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2585 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002586 .build()));
2587 // The pointer_down event should be ignored
2588 window->assertNoEvents();
2589}
2590
2591/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002592 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2593 * the injected event.
2594 */
2595TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2597 sp<FakeWindowHandle> window =
2598 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2599 window->setFrame(Rect(0, 0, 400, 400));
2600
2601 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2602
2603 const int32_t touchDeviceId = 4;
2604 NotifyMotionArgs args;
2605 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2606 // completion.
2607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2608 injectMotionEvent(mDispatcher,
2609 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2610 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002611 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002612 .x(50)
2613 .y(50))
2614 .build()));
2615 window->consumeMotionEvent(
2616 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2617
2618 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2619 // should be canceled and the new gesture should take over.
2620 mDispatcher->notifyMotion(&(
2621 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002623 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002624 .build()));
2625
2626 window->consumeMotionEvent(
2627 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2628 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2629}
2630
2631/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002632 * This test is similar to the test above, but the sequence of injected events is different.
2633 *
2634 * Two windows: a window on the left and a window on the right.
2635 * Mouse is hovered over the left window.
2636 * Next, we tap on the left window, where the cursor was last seen.
2637 *
2638 * After that, we inject one finger down onto the right window, and then a second finger down onto
2639 * the left window.
2640 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2641 * window (first), and then another on the left window (second).
2642 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2643 * In the buggy implementation, second finger down on the left window would cause a crash.
2644 */
2645TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2647 sp<FakeWindowHandle> leftWindow =
2648 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2649 leftWindow->setFrame(Rect(0, 0, 200, 200));
2650
2651 sp<FakeWindowHandle> rightWindow =
2652 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2653 rightWindow->setFrame(Rect(200, 0, 400, 200));
2654
2655 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2656
2657 const int32_t mouseDeviceId = 6;
2658 const int32_t touchDeviceId = 4;
2659 // Hover over the left window. Keep the cursor there.
2660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2661 injectMotionEvent(mDispatcher,
2662 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2663 AINPUT_SOURCE_MOUSE)
2664 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002665 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002666 .x(50)
2667 .y(50))
2668 .build()));
2669 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2670
2671 // Tap on left window
2672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2673 injectMotionEvent(mDispatcher,
2674 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2675 AINPUT_SOURCE_TOUCHSCREEN)
2676 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002677 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002678 .x(100)
2679 .y(100))
2680 .build()));
2681
2682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2683 injectMotionEvent(mDispatcher,
2684 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2685 AINPUT_SOURCE_TOUCHSCREEN)
2686 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002687 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002688 .x(100)
2689 .y(100))
2690 .build()));
2691 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2692 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2693 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2694
2695 // First finger down on right window
2696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2697 injectMotionEvent(mDispatcher,
2698 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2699 AINPUT_SOURCE_TOUCHSCREEN)
2700 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002701 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002702 .x(300)
2703 .y(100))
2704 .build()));
2705 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2706
2707 // Second finger down on the left window
2708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2709 injectMotionEvent(mDispatcher,
2710 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2711 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002712 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002713 .x(300)
2714 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002715 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002716 .x(100)
2717 .y(100))
2718 .build()));
2719 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2720 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2721
2722 // No more events
2723 leftWindow->assertNoEvents();
2724 rightWindow->assertNoEvents();
2725}
2726
2727/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002728 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2729 * While the touch is down, new hover events from the stylus device should be ignored. After the
2730 * touch is gone, stylus hovering should start working again.
2731 */
2732TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2734 sp<FakeWindowHandle> window =
2735 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2736 window->setFrame(Rect(0, 0, 200, 200));
2737
2738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2739
2740 const int32_t stylusDeviceId = 5;
2741 const int32_t touchDeviceId = 4;
2742 // Start hovering with stylus
2743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2744 injectMotionEvent(mDispatcher,
2745 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2746 AINPUT_SOURCE_STYLUS)
2747 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002748 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002749 .x(50)
2750 .y(50))
2751 .build()));
2752 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2753
2754 // Finger down on the window
2755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2756 injectMotionEvent(mDispatcher,
2757 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2758 AINPUT_SOURCE_TOUCHSCREEN)
2759 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002760 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002761 .x(100)
2762 .y(100))
2763 .build()));
2764 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2765 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2766
2767 // Try to continue hovering with stylus. Since we are already down, injection should fail
2768 ASSERT_EQ(InputEventInjectionResult::FAILED,
2769 injectMotionEvent(mDispatcher,
2770 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2771 AINPUT_SOURCE_STYLUS)
2772 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002773 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002774 .x(50)
2775 .y(50))
2776 .build()));
2777 // No event should be sent. This event should be ignored because a pointer from another device
2778 // is already down.
2779
2780 // Lift up the finger
2781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2782 injectMotionEvent(mDispatcher,
2783 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2784 AINPUT_SOURCE_TOUCHSCREEN)
2785 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002786 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002787 .x(100)
2788 .y(100))
2789 .build()));
2790 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2791
2792 // Now that the touch is gone, stylus hovering should start working again
2793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2794 injectMotionEvent(mDispatcher,
2795 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2796 AINPUT_SOURCE_STYLUS)
2797 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002798 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002799 .x(50)
2800 .y(50))
2801 .build()));
2802 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2803 // No more events
2804 window->assertNoEvents();
2805}
2806
2807/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002808 * A spy window above a window with no input channel.
2809 * Start hovering with a stylus device, and then tap with it.
2810 * Ensure spy window receives the entire sequence.
2811 */
2812TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2814 sp<FakeWindowHandle> spyWindow =
2815 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2816 spyWindow->setFrame(Rect(0, 0, 200, 200));
2817 spyWindow->setTrustedOverlay(true);
2818 spyWindow->setSpy(true);
2819 sp<FakeWindowHandle> window =
2820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2821 window->setNoInputChannel(true);
2822 window->setFrame(Rect(0, 0, 200, 200));
2823
2824 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2825
2826 NotifyMotionArgs args;
2827
2828 // Start hovering with stylus
2829 mDispatcher->notifyMotion(
2830 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002831 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002832 .build()));
2833 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2834 // Stop hovering
2835 mDispatcher->notifyMotion(
2836 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002837 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002838 .build()));
2839 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2840
2841 // Stylus touches down
2842 mDispatcher->notifyMotion(
2843 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002845 .build()));
2846 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2847
2848 // Stylus goes up
2849 mDispatcher->notifyMotion(
2850 &(args = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002852 .build()));
2853 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2854
2855 // Again hover
2856 mDispatcher->notifyMotion(
2857 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002858 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002859 .build()));
2860 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2861 // Stop hovering
2862 mDispatcher->notifyMotion(
2863 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002864 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865 .build()));
2866 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2867
2868 // No more events
2869 spyWindow->assertNoEvents();
2870 window->assertNoEvents();
2871}
2872
2873/**
2874 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2875 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2876 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2877 * While the mouse is down, new move events from the touch device should be ignored.
2878 */
2879TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2881 sp<FakeWindowHandle> spyWindow =
2882 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2883 spyWindow->setFrame(Rect(0, 0, 200, 200));
2884 spyWindow->setTrustedOverlay(true);
2885 spyWindow->setSpy(true);
2886 sp<FakeWindowHandle> window =
2887 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2888 window->setFrame(Rect(0, 0, 200, 200));
2889
2890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2891
2892 const int32_t mouseDeviceId = 7;
2893 const int32_t touchDeviceId = 4;
2894 NotifyMotionArgs args;
2895
2896 // Hover a bit with mouse first
2897 mDispatcher->notifyMotion(&(
2898 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2899 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002901 .build()));
2902 spyWindow->consumeMotionEvent(
2903 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2904 window->consumeMotionEvent(
2905 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2906
2907 // Start touching
2908 mDispatcher->notifyMotion(
2909 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2910 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002911 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002912 .build()));
2913 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2914 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2915 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2916 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2917
2918 mDispatcher->notifyMotion(
2919 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2920 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002921 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002922 .build()));
2923 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2924 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2925
2926 // Pilfer the stream
2927 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2928 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2929
2930 mDispatcher->notifyMotion(
2931 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2932 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002933 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002934 .build()));
2935 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2936
2937 // Mouse down
2938 mDispatcher->notifyMotion(&(
2939 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2940 .deviceId(mouseDeviceId)
2941 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002942 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002943 .build()));
2944
2945 spyWindow->consumeMotionEvent(
2946 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2947 spyWindow->consumeMotionEvent(
2948 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2949 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2950
2951 mDispatcher->notifyMotion(&(
2952 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2953 .deviceId(mouseDeviceId)
2954 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2955 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002957 .build()));
2958 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2959 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2960
2961 // Mouse move!
2962 mDispatcher->notifyMotion(&(
2963 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2964 .deviceId(mouseDeviceId)
2965 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002967 .build()));
2968 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2969 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2970
2971 // Touch move!
2972 mDispatcher->notifyMotion(
2973 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2974 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002975 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002976 .build()));
2977
2978 // No more events
2979 spyWindow->assertNoEvents();
2980 window->assertNoEvents();
2981}
2982
2983/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002984 * On the display, have a single window, and also an area where there's no window.
2985 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2986 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2987 */
2988TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2990 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002991 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002992
2993 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2994 NotifyMotionArgs args;
2995
2996 // Touch down on the empty space
2997 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2998
2999 mDispatcher->waitForIdle();
3000 window->assertNoEvents();
3001
3002 // Now touch down on the window with another pointer
3003 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
3004 mDispatcher->waitForIdle();
3005 window->consumeMotionDown();
3006}
3007
3008/**
3009 * Same test as above, but instead of touching the empty space, the first touch goes to
3010 * non-touchable window.
3011 */
3012TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3014 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003015 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003016 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3017 window1->setTouchable(false);
3018 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003019 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003020 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3021
3022 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3023
3024 NotifyMotionArgs args;
3025 // Touch down on the non-touchable window
3026 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
3027
3028 mDispatcher->waitForIdle();
3029 window1->assertNoEvents();
3030 window2->assertNoEvents();
3031
3032 // Now touch down on the window with another pointer
3033 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
3034 mDispatcher->waitForIdle();
3035 window2->consumeMotionDown();
3036}
3037
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003038/**
3039 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3040 * to the event time of the first ACTION_DOWN sent to the particular window.
3041 */
3042TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3044 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003045 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003046 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3047 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003048 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003049 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3050
3051 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3052
3053 NotifyMotionArgs args;
3054 // Touch down on the first window
3055 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
3056
3057 mDispatcher->waitForIdle();
3058 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003059 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003060 window2->assertNoEvents();
3061 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3062 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3063 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3064
3065 // Now touch down on the window with another pointer
3066 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
3067 mDispatcher->waitForIdle();
3068 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003069 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003070 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3071 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3072 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3073 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3074
3075 // Now move the pointer on the second window
3076 mDispatcher->notifyMotion(
3077 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
3078 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003079 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003080
3081 // Now add new touch down on the second window
3082 mDispatcher->notifyMotion(
3083 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
3084 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003085 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003086
3087 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3088 window1->consumeMotionMove();
3089 window1->assertNoEvents();
3090
3091 // Now move the pointer on the first window
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08003092 mDispatcher->notifyMotion(&(
3093 args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}})));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003094 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003095 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003096
3097 mDispatcher->notifyMotion(&(
3098 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
3099 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003100 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003101}
3102
Garfield Tandf26e862020-07-01 20:18:19 -07003103TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003105 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003106 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003107 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003108 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003109 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003110 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003111
3112 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3113
3114 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3115
3116 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003118 injectMotionEvent(mDispatcher,
3119 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3120 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003121 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003122 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003123 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003124
3125 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003127 injectMotionEvent(mDispatcher,
3128 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3129 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003130 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003131 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003132 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3133 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003134
3135 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003137 injectMotionEvent(mDispatcher,
3138 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3139 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003140 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003141 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003142 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3143 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003144
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003146 injectMotionEvent(mDispatcher,
3147 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3148 AINPUT_SOURCE_MOUSE)
3149 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3150 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003151 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003152 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003153 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003154
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003156 injectMotionEvent(mDispatcher,
3157 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3158 AINPUT_SOURCE_MOUSE)
3159 .buttonState(0)
3160 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003161 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003162 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003163 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003164
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003166 injectMotionEvent(mDispatcher,
3167 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3168 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003169 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003170 .build()));
3171 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3172
3173 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003175 injectMotionEvent(mDispatcher,
3176 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3177 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003178 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003179 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003180 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003181
3182 // No more events
3183 windowLeft->assertNoEvents();
3184 windowRight->assertNoEvents();
3185}
3186
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003187/**
3188 * Put two fingers down (and don't release them) and click the mouse button.
3189 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3190 * currently active gesture should be canceled, and the new one should proceed.
3191 */
3192TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3194 sp<FakeWindowHandle> window =
3195 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3196 window->setFrame(Rect(0, 0, 600, 800));
3197
3198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3199
3200 const int32_t touchDeviceId = 4;
3201 const int32_t mouseDeviceId = 6;
3202 NotifyMotionArgs args;
3203
3204 // Two pointers down
3205 mDispatcher->notifyMotion(&(
3206 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3207 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003208 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003209 .build()));
3210
3211 mDispatcher->notifyMotion(&(
3212 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3213 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003214 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3215 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003216 .build()));
3217 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3218 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3219
3220 // Inject a series of mouse events for a mouse click
3221 mDispatcher->notifyMotion(&(
3222 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3223 .deviceId(mouseDeviceId)
3224 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003225 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003226 .build()));
3227 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3228 WithPointerCount(2u)));
3229 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3230
3231 mDispatcher->notifyMotion(&(
3232 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3233 .deviceId(mouseDeviceId)
3234 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3235 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003236 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003237 .build()));
3238 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3239
3240 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3241 // already canceled gesture, it should be ignored.
3242 mDispatcher->notifyMotion(&(
3243 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3244 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003245 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3246 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003247 .build()));
3248 window->assertNoEvents();
3249}
3250
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003251TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3253
3254 sp<FakeWindowHandle> spyWindow =
3255 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3256 spyWindow->setFrame(Rect(0, 0, 600, 800));
3257 spyWindow->setTrustedOverlay(true);
3258 spyWindow->setSpy(true);
3259 sp<FakeWindowHandle> window =
3260 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3261 window->setFrame(Rect(0, 0, 600, 800));
3262
3263 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3264 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3265
3266 // Send mouse cursor to the window
3267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3268 injectMotionEvent(mDispatcher,
3269 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3270 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003271 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003272 .x(100)
3273 .y(100))
3274 .build()));
3275
3276 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3277 WithSource(AINPUT_SOURCE_MOUSE)));
3278 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3279 WithSource(AINPUT_SOURCE_MOUSE)));
3280
3281 window->assertNoEvents();
3282 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003283}
3284
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003285TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3287
3288 sp<FakeWindowHandle> spyWindow =
3289 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3290 spyWindow->setFrame(Rect(0, 0, 600, 800));
3291 spyWindow->setTrustedOverlay(true);
3292 spyWindow->setSpy(true);
3293 sp<FakeWindowHandle> window =
3294 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3295 window->setFrame(Rect(0, 0, 600, 800));
3296
3297 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3299
3300 // Send mouse cursor to the window
3301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3302 injectMotionEvent(mDispatcher,
3303 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3304 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003305 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003306 .x(100)
3307 .y(100))
3308 .build()));
3309
3310 // Move mouse cursor
3311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3312 injectMotionEvent(mDispatcher,
3313 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3314 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003315 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003316 .x(110)
3317 .y(110))
3318 .build()));
3319
3320 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3321 WithSource(AINPUT_SOURCE_MOUSE)));
3322 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3323 WithSource(AINPUT_SOURCE_MOUSE)));
3324 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3325 WithSource(AINPUT_SOURCE_MOUSE)));
3326 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3327 WithSource(AINPUT_SOURCE_MOUSE)));
3328 // Touch down on the window
3329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3330 injectMotionEvent(mDispatcher,
3331 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3332 AINPUT_SOURCE_TOUCHSCREEN)
3333 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003334 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003335 .x(200)
3336 .y(200))
3337 .build()));
3338 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3339 WithSource(AINPUT_SOURCE_MOUSE)));
3340 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3341 WithSource(AINPUT_SOURCE_MOUSE)));
3342 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3343 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3344 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3345 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3346
3347 // pilfer the motion, retaining the gesture on the spy window.
3348 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3349 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3350 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3351
3352 // Touch UP on the window
3353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3354 injectMotionEvent(mDispatcher,
3355 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3356 AINPUT_SOURCE_TOUCHSCREEN)
3357 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003358 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003359 .x(200)
3360 .y(200))
3361 .build()));
3362 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3363 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3364
3365 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3366 // to send a new gesture. It should again go to both windows (spy and the window below), just
3367 // like the first gesture did, before pilfering. The window configuration has not changed.
3368
3369 // One more tap - DOWN
3370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3371 injectMotionEvent(mDispatcher,
3372 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3373 AINPUT_SOURCE_TOUCHSCREEN)
3374 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003375 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003376 .x(250)
3377 .y(250))
3378 .build()));
3379 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3380 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3381 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3382 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3383
3384 // Touch UP on the window
3385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3386 injectMotionEvent(mDispatcher,
3387 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3388 AINPUT_SOURCE_TOUCHSCREEN)
3389 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003390 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003391 .x(250)
3392 .y(250))
3393 .build()));
3394 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3395 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3396 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3397 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3398
3399 window->assertNoEvents();
3400 spyWindow->assertNoEvents();
3401}
3402
Garfield Tandf26e862020-07-01 20:18:19 -07003403// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3404// directly in this test.
3405TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003407 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003408 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003409 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003410
3411 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3412
3413 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3414
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003416 injectMotionEvent(mDispatcher,
3417 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3418 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003420 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003421 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003422 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003424 injectMotionEvent(mDispatcher,
3425 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3426 .buttonState(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 Vishniakouf372b812023-02-14 18:06:51 -08003429 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3430 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003431
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003433 injectMotionEvent(mDispatcher,
3434 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3435 AINPUT_SOURCE_MOUSE)
3436 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3437 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003438 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003439 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003440 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003441
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003443 injectMotionEvent(mDispatcher,
3444 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3445 AINPUT_SOURCE_MOUSE)
3446 .buttonState(0)
3447 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003449 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003450 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003451
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003453 injectMotionEvent(mDispatcher,
3454 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3455 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003456 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003457 .build()));
3458 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3459
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003461 injectMotionEvent(mDispatcher,
3462 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3463 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003464 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003465 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003466 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003467}
3468
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003469/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003470 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3471 * is generated.
3472 */
3473TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3475 sp<FakeWindowHandle> window =
3476 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3477 window->setFrame(Rect(0, 0, 1200, 800));
3478
3479 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3480
3481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3482
3483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3484 injectMotionEvent(mDispatcher,
3485 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3486 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003487 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003488 .x(300)
3489 .y(400))
3490 .build()));
3491 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3492
3493 // Remove the window, but keep the channel.
3494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3495 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3496}
3497
3498/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003499 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3500 */
3501TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3502 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3503 sp<FakeWindowHandle> window =
3504 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3505 window->setFrame(Rect(0, 0, 100, 100));
3506
3507 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3508
3509 const int32_t mouseDeviceId = 7;
3510 const int32_t touchDeviceId = 4;
3511 NotifyMotionArgs args;
3512
3513 // Start hovering with the mouse
3514 mDispatcher->notifyMotion(
3515 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3516 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003517 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003518 .build()));
3519 window->consumeMotionEvent(
3520 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3521
3522 // Touch goes down
3523 mDispatcher->notifyMotion(
3524 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3525 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003526 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003527 .build()));
3528
3529 window->consumeMotionEvent(
3530 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3531 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3532}
3533
3534/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003535 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003536 * The tap causes a HOVER_EXIT event to be generated because the current event
3537 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003538 */
3539TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3541 sp<FakeWindowHandle> window =
3542 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3543 window->setFrame(Rect(0, 0, 100, 100));
3544
3545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3546
3547 // Inject a hover_move from mouse.
3548 NotifyMotionArgs motionArgs =
3549 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3550 ADISPLAY_ID_DEFAULT, {{50, 50}});
3551 motionArgs.xCursorPosition = 50;
3552 motionArgs.yCursorPosition = 50;
3553 mDispatcher->notifyMotion(&motionArgs);
3554 ASSERT_NO_FATAL_FAILURE(
3555 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3556 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003557
3558 // Tap on the window
3559 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3560 ADISPLAY_ID_DEFAULT, {{10, 10}});
3561 mDispatcher->notifyMotion(&motionArgs);
3562 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003563 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3564 WithSource(AINPUT_SOURCE_MOUSE))));
3565
3566 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003567 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3568 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3569
3570 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3571 ADISPLAY_ID_DEFAULT, {{10, 10}});
3572 mDispatcher->notifyMotion(&motionArgs);
3573 ASSERT_NO_FATAL_FAILURE(
3574 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3575 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3576}
3577
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003578TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3579 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3580 sp<FakeWindowHandle> windowDefaultDisplay =
3581 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3582 ADISPLAY_ID_DEFAULT);
3583 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3584 sp<FakeWindowHandle> windowSecondDisplay =
3585 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3586 SECOND_DISPLAY_ID);
3587 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3588
3589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3590 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3591
3592 // Set cursor position in window in default display and check that hover enter and move
3593 // events are generated.
3594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3595 injectMotionEvent(mDispatcher,
3596 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3597 AINPUT_SOURCE_MOUSE)
3598 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003599 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003600 .x(300)
3601 .y(600))
3602 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003603 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003604
3605 // Remove all windows in secondary display and check that no event happens on window in
3606 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003607 mDispatcher->setInputWindows(
3608 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003609 windowDefaultDisplay->assertNoEvents();
3610
3611 // Move cursor position in window in default display and check that only hover move
3612 // event is generated and not hover enter event.
3613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3614 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3616 injectMotionEvent(mDispatcher,
3617 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3618 AINPUT_SOURCE_MOUSE)
3619 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003620 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003621 .x(400)
3622 .y(700))
3623 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003624 windowDefaultDisplay->consumeMotionEvent(
3625 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3626 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003627 windowDefaultDisplay->assertNoEvents();
3628}
3629
Garfield Tan00f511d2019-06-12 16:55:40 -07003630TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003632
3633 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003634 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003635 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003636 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003637 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003638 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003639
3640 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3641
Arthur Hung72d8dc32020-03-28 00:48:39 +00003642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003643
3644 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3645 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003647 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003648 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003649 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003650 windowRight->assertNoEvents();
3651}
3652
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003653TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003655 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3656 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003657 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003658
Arthur Hung72d8dc32020-03-28 00:48:39 +00003659 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003660 setFocusedWindow(window);
3661
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003662 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003663
3664 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3665 mDispatcher->notifyKey(&keyArgs);
3666
3667 // Window should receive key down event.
3668 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3669
3670 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3671 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003672 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003673 mDispatcher->notifyDeviceReset(&args);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003674 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003675 AKEY_EVENT_FLAG_CANCELED);
3676}
3677
3678TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003680 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3681 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003682
Arthur Hung72d8dc32020-03-28 00:48:39 +00003683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003684
3685 NotifyMotionArgs motionArgs =
3686 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3687 ADISPLAY_ID_DEFAULT);
3688 mDispatcher->notifyMotion(&motionArgs);
3689
3690 // Window should receive motion down event.
3691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3692
3693 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3694 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003695 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003696 mDispatcher->notifyDeviceReset(&args);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003697 window->consumeMotionEvent(
3698 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003699}
3700
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003701TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3704 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003705 window->setFocusable(true);
3706
3707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3708 setFocusedWindow(window);
3709
3710 window->consumeFocusEvent(true);
3711
3712 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3713 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3714 const nsecs_t injectTime = keyArgs.eventTime;
3715 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
3716 mDispatcher->notifyKey(&keyArgs);
3717 // The dispatching time should be always greater than or equal to intercept key timeout.
3718 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3719 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3720 std::chrono::nanoseconds(interceptKeyTimeout).count());
3721}
3722
3723TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003725 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3726 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003727 window->setFocusable(true);
3728
3729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3730 setFocusedWindow(window);
3731
3732 window->consumeFocusEvent(true);
3733
3734 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3735 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3736 mFakePolicy->setInterceptKeyTimeout(150ms);
3737 mDispatcher->notifyKey(&keyDown);
3738 mDispatcher->notifyKey(&keyUp);
3739
3740 // Window should receive key event immediately when same key up.
3741 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3742 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3743}
3744
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003745/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003746 * Two windows. First is a regular window. Second does not overlap with the first, and has
3747 * WATCH_OUTSIDE_TOUCH.
3748 * Both windows are owned by the same UID.
3749 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3750 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3751 */
3752TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3755 "First Window", ADISPLAY_ID_DEFAULT);
3756 window->setFrame(Rect{0, 0, 100, 100});
3757
3758 sp<FakeWindowHandle> outsideWindow =
3759 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3760 ADISPLAY_ID_DEFAULT);
3761 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3762 outsideWindow->setWatchOutsideTouch(true);
3763 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3764 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3765
3766 // Tap on first window.
3767 NotifyMotionArgs motionArgs =
3768 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3769 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
3770 mDispatcher->notifyMotion(&motionArgs);
3771 window->consumeMotionDown();
3772 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3773 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3774 outsideWindow->consumeMotionEvent(
3775 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3776}
3777
3778/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003779 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3780 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3781 * ACTION_OUTSIDE event is sent per gesture.
3782 */
3783TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3784 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3787 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003788 window->setWatchOutsideTouch(true);
3789 window->setFrame(Rect{0, 0, 100, 100});
3790 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003791 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3792 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003793 secondWindow->setFrame(Rect{100, 100, 200, 200});
3794 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003795 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3796 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003797 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3799
3800 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
3801 NotifyMotionArgs motionArgs =
3802 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3803 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
3804 mDispatcher->notifyMotion(&motionArgs);
3805 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.
3810 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3811 {PointF{-10, -10}, PointF{105, 105}});
3812 mDispatcher->notifyMotion(&motionArgs);
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.
3821 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3822 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
3823 mDispatcher->notifyMotion(&motionArgs);
3824 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
3840 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3841 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3842 mDispatcher->notifyKey(&keyDown);
3843 mDispatcher->notifyKey(&keyUp);
3844
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
3853 mDispatcher->notifyKey(&keyDown);
3854 mDispatcher->notifyKey(&keyUp);
3855 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 Pradhanc44ce4d2021-10-05 05:26:29 -07003962 NotifyMotionArgs downMotionArgs =
3963 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3964 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
3965 mDispatcher->notifyMotion(&downMotionArgs);
3966
3967 firstWindow->consumeMotionDown();
3968 secondWindow->assertNoEvents();
3969}
3970
3971// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3972// the event should be treated as being in the logical display space.
3973TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3974 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3975 // Send down to the first window. The point is represented in the logical display space. The
3976 // point is selected so that if the hit test was done in logical display space, then it would
3977 // end up in the incorrect window.
3978 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3979 PointF{75 * 2, 55 * 4});
3980
3981 firstWindow->consumeMotionDown();
3982 secondWindow->assertNoEvents();
3983}
3984
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003985// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3986// event should be treated as being in the logical display space.
3987TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3988 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3989
3990 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3991 ui::Transform injectedEventTransform;
3992 injectedEventTransform.set(matrix);
3993 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3994 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3995
3996 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3997 .displayId(ADISPLAY_ID_DEFAULT)
3998 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003999 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004000 .x(untransformedPoint.x)
4001 .y(untransformedPoint.y))
4002 .build();
4003 event.transform(matrix);
4004
4005 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4006 InputEventInjectionSync::WAIT_FOR_RESULT);
4007
4008 firstWindow->consumeMotionDown();
4009 secondWindow->assertNoEvents();
4010}
4011
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004012TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4013 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4014
4015 // Send down to the second window.
4016 NotifyMotionArgs downMotionArgs =
4017 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4018 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
4019 mDispatcher->notifyMotion(&downMotionArgs);
4020
4021 firstWindow->assertNoEvents();
4022 const MotionEvent* event = secondWindow->consumeMotion();
4023 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4024
4025 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4026 EXPECT_EQ(300, event->getRawX(0));
4027 EXPECT_EQ(880, event->getRawY(0));
4028
4029 // Ensure that the x and y values are in the window's coordinate space.
4030 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4031 // the logical display space. This will be the origin of the window space.
4032 EXPECT_EQ(100, event->getX(0));
4033 EXPECT_EQ(80, event->getY(0));
4034}
4035
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004036/** Ensure consistent behavior of InputDispatcher in all orientations. */
4037class InputDispatcherDisplayOrientationFixture
4038 : public InputDispatcherDisplayProjectionTest,
4039 public ::testing::WithParamInterface<ui::Rotation> {};
4040
4041// This test verifies the touchable region of a window for all rotations of the display by tapping
4042// in different locations on the display, specifically points close to the four corners of a
4043// window.
4044TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4045 constexpr static int32_t displayWidth = 400;
4046 constexpr static int32_t displayHeight = 800;
4047
4048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4049
4050 const auto rotation = GetParam();
4051
4052 // Set up the display with the specified rotation.
4053 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4054 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4055 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4056 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4057 logicalDisplayWidth, logicalDisplayHeight);
4058 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4059
4060 // Create a window with its bounds determined in the logical display.
4061 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4062 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4063 sp<FakeWindowHandle> window =
4064 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4065 window->setFrame(frameInDisplay, displayTransform);
4066 addWindow(window);
4067
4068 // The following points in logical display space should be inside the window.
4069 static const std::array<vec2, 4> insidePoints{
4070 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4071 for (const auto pointInsideWindow : insidePoints) {
4072 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4073 const PointF pointInDisplaySpace{p.x, p.y};
4074 const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4075 ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
4076 mDispatcher->notifyMotion(&down);
4077 window->consumeMotionDown();
4078
4079 const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4080 ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
4081 mDispatcher->notifyMotion(&up);
4082 window->consumeMotionUp();
4083 }
4084
4085 // The following points in logical display space should be outside the window.
4086 static const std::array<vec2, 5> outsidePoints{
4087 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4088 for (const auto pointOutsideWindow : outsidePoints) {
4089 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4090 const PointF pointInDisplaySpace{p.x, p.y};
4091 const auto down = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4092 ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
4093 mDispatcher->notifyMotion(&down);
4094
4095 const auto up = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4096 ADISPLAY_ID_DEFAULT, {pointInDisplaySpace});
4097 mDispatcher->notifyMotion(&up);
4098 }
4099 window->assertNoEvents();
4100}
4101
4102// Run the precision tests for all rotations.
4103INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4104 InputDispatcherDisplayOrientationFixture,
4105 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4106 ui::ROTATION_270),
4107 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4108 return ftl::enum_string(testParamInfo.param);
4109 });
4110
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004111using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4112 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004113
4114class TransferTouchFixture : public InputDispatcherTest,
4115 public ::testing::WithParamInterface<TransferFunction> {};
4116
4117TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004119
4120 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004121 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004122 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4123 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004124 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004125 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004126 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4127 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004128 sp<FakeWindowHandle> wallpaper =
4129 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4130 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004131 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004133
4134 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004135 NotifyMotionArgs downMotionArgs =
4136 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4137 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004138 mDispatcher->notifyMotion(&downMotionArgs);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004139
Svet Ganov5d3bc372020-01-26 23:11:07 -08004140 // Only the first window should get the down event
4141 firstWindow->consumeMotionDown();
4142 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004143 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004144
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004145 // Transfer touch to the second window
4146 TransferFunction f = GetParam();
4147 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4148 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004149 // The first window gets cancel and the second gets down
4150 firstWindow->consumeMotionCancel();
4151 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004152 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004153
4154 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004155 NotifyMotionArgs upMotionArgs =
4156 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4157 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004158 mDispatcher->notifyMotion(&upMotionArgs);
4159 // The first window gets no events and the second gets up
4160 firstWindow->assertNoEvents();
4161 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004162 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004163}
4164
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004165/**
4166 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4167 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4168 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4169 * natural to the user.
4170 * In this test, we are sending a pointer to both spy window and first window. We then try to
4171 * transfer touch to the second window. The dispatcher should identify the first window as the
4172 * one that should lose the gesture, and therefore the action should be to move the gesture from
4173 * the first window to the second.
4174 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4175 * the other API, as well.
4176 */
4177TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4179
4180 // Create a couple of windows + a spy window
4181 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004182 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004183 spyWindow->setTrustedOverlay(true);
4184 spyWindow->setSpy(true);
4185 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004186 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004187 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004188 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004189
4190 // Add the windows to the dispatcher
4191 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4192
4193 // Send down to the first window
4194 NotifyMotionArgs downMotionArgs =
4195 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4196 ADISPLAY_ID_DEFAULT);
4197 mDispatcher->notifyMotion(&downMotionArgs);
4198 // Only the first window and spy should get the down event
4199 spyWindow->consumeMotionDown();
4200 firstWindow->consumeMotionDown();
4201
4202 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4203 // if f === 'transferTouch'.
4204 TransferFunction f = GetParam();
4205 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4206 ASSERT_TRUE(success);
4207 // The first window gets cancel and the second gets down
4208 firstWindow->consumeMotionCancel();
4209 secondWindow->consumeMotionDown();
4210
4211 // Send up event to the second window
4212 NotifyMotionArgs upMotionArgs =
4213 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4214 ADISPLAY_ID_DEFAULT);
4215 mDispatcher->notifyMotion(&upMotionArgs);
4216 // The first window gets no events and the second+spy get up
4217 firstWindow->assertNoEvents();
4218 spyWindow->consumeMotionUp();
4219 secondWindow->consumeMotionUp();
4220}
4221
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004222TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004224
4225 PointF touchPoint = {10, 10};
4226
4227 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004228 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004229 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4230 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004231 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004232 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004233 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4234 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004235 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004236
4237 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004239
4240 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004241 NotifyMotionArgs downMotionArgs =
4242 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4243 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244 mDispatcher->notifyMotion(&downMotionArgs);
4245 // Only the first window should get the down event
4246 firstWindow->consumeMotionDown();
4247 secondWindow->assertNoEvents();
4248
4249 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004250 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004251 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004252 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004253 mDispatcher->notifyMotion(&pointerDownMotionArgs);
4254 // Only the first window should get the pointer down event
4255 firstWindow->consumeMotionPointerDown(1);
4256 secondWindow->assertNoEvents();
4257
4258 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004259 TransferFunction f = GetParam();
4260 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4261 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004262 // The first window gets cancel and the second gets down and pointer down
4263 firstWindow->consumeMotionCancel();
4264 secondWindow->consumeMotionDown();
4265 secondWindow->consumeMotionPointerDown(1);
4266
4267 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004268 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004269 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004270 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004271 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4272 // The first window gets nothing and the second gets pointer up
4273 firstWindow->assertNoEvents();
4274 secondWindow->consumeMotionPointerUp(1);
4275
4276 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004277 NotifyMotionArgs upMotionArgs =
4278 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4279 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004280 mDispatcher->notifyMotion(&upMotionArgs);
4281 // The first window gets nothing and the second gets up
4282 firstWindow->assertNoEvents();
4283 secondWindow->consumeMotionUp();
4284}
4285
Arthur Hungc539dbb2022-12-08 07:45:36 +00004286TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4288
4289 // Create a couple of windows
4290 sp<FakeWindowHandle> firstWindow =
4291 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4292 ADISPLAY_ID_DEFAULT);
4293 firstWindow->setDupTouchToWallpaper(true);
4294 sp<FakeWindowHandle> secondWindow =
4295 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4296 ADISPLAY_ID_DEFAULT);
4297 secondWindow->setDupTouchToWallpaper(true);
4298
4299 sp<FakeWindowHandle> wallpaper1 =
4300 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4301 wallpaper1->setIsWallpaper(true);
4302
4303 sp<FakeWindowHandle> wallpaper2 =
4304 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4305 wallpaper2->setIsWallpaper(true);
4306 // Add the windows to the dispatcher
4307 mDispatcher->setInputWindows(
4308 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4309
4310 // Send down to the first window
4311 NotifyMotionArgs downMotionArgs =
4312 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4313 ADISPLAY_ID_DEFAULT);
4314 mDispatcher->notifyMotion(&downMotionArgs);
4315
4316 // Only the first window should get the down event
4317 firstWindow->consumeMotionDown();
4318 secondWindow->assertNoEvents();
4319 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4320 wallpaper2->assertNoEvents();
4321
4322 // Transfer touch focus to the second window
4323 TransferFunction f = GetParam();
4324 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4325 ASSERT_TRUE(success);
4326
4327 // The first window gets cancel and the second gets down
4328 firstWindow->consumeMotionCancel();
4329 secondWindow->consumeMotionDown();
4330 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4331 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4332
4333 // Send up event to the second window
4334 NotifyMotionArgs upMotionArgs =
4335 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4336 ADISPLAY_ID_DEFAULT);
4337 mDispatcher->notifyMotion(&upMotionArgs);
4338 // The first window gets no events and the second gets up
4339 firstWindow->assertNoEvents();
4340 secondWindow->consumeMotionUp();
4341 wallpaper1->assertNoEvents();
4342 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4343}
4344
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004345// For the cases of single pointer touch and two pointers non-split touch, the api's
4346// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4347// for the case where there are multiple pointers split across several windows.
4348INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4349 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004350 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4351 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004352 return dispatcher->transferTouch(destChannelToken,
4353 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004354 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004355 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4356 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004357 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004358 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004359 }));
4360
Svet Ganov5d3bc372020-01-26 23:11:07 -08004361TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004362 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004363
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004364 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004365 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4366 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004367 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004368
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004369 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004370 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4371 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004372 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004373
4374 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004376
4377 PointF pointInFirst = {300, 200};
4378 PointF pointInSecond = {300, 600};
4379
4380 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004381 NotifyMotionArgs firstDownMotionArgs =
4382 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4383 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004384 mDispatcher->notifyMotion(&firstDownMotionArgs);
4385 // Only the first window should get the down event
4386 firstWindow->consumeMotionDown();
4387 secondWindow->assertNoEvents();
4388
4389 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004390 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004391 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004392 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004393 mDispatcher->notifyMotion(&secondDownMotionArgs);
4394 // The first window gets a move and the second a down
4395 firstWindow->consumeMotionMove();
4396 secondWindow->consumeMotionDown();
4397
4398 // Transfer touch focus to the second window
4399 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4400 // The first window gets cancel and the new gets pointer down (it already saw down)
4401 firstWindow->consumeMotionCancel();
4402 secondWindow->consumeMotionPointerDown(1);
4403
4404 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004405 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004406 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004407 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004408 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4409 // The first window gets nothing and the second gets pointer up
4410 firstWindow->assertNoEvents();
4411 secondWindow->consumeMotionPointerUp(1);
4412
4413 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004414 NotifyMotionArgs upMotionArgs =
4415 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4416 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004417 mDispatcher->notifyMotion(&upMotionArgs);
4418 // The first window gets nothing and the second gets up
4419 firstWindow->assertNoEvents();
4420 secondWindow->consumeMotionUp();
4421}
4422
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004423// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4424// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4425// touch is not supported, so the touch should continue on those windows and the transferred-to
4426// window should get nothing.
4427TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4429
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004430 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004431 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4432 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004433 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004434
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004435 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004436 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4437 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004438 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004439
4440 // Add the windows to the dispatcher
4441 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4442
4443 PointF pointInFirst = {300, 200};
4444 PointF pointInSecond = {300, 600};
4445
4446 // Send down to the first window
4447 NotifyMotionArgs firstDownMotionArgs =
4448 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4449 ADISPLAY_ID_DEFAULT, {pointInFirst});
4450 mDispatcher->notifyMotion(&firstDownMotionArgs);
4451 // Only the first window should get the down event
4452 firstWindow->consumeMotionDown();
4453 secondWindow->assertNoEvents();
4454
4455 // Send down to the second window
4456 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004457 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004458 {pointInFirst, pointInSecond});
4459 mDispatcher->notifyMotion(&secondDownMotionArgs);
4460 // The first window gets a move and the second a down
4461 firstWindow->consumeMotionMove();
4462 secondWindow->consumeMotionDown();
4463
4464 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004465 const bool transferred =
4466 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004467 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4468 ASSERT_FALSE(transferred);
4469 firstWindow->assertNoEvents();
4470 secondWindow->assertNoEvents();
4471
4472 // The rest of the dispatch should proceed as normal
4473 // Send pointer up to the second window
4474 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004475 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004476 {pointInFirst, pointInSecond});
4477 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4478 // The first window gets MOVE and the second gets pointer up
4479 firstWindow->consumeMotionMove();
4480 secondWindow->consumeMotionUp();
4481
4482 // Send up event to the first window
4483 NotifyMotionArgs upMotionArgs =
4484 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4485 ADISPLAY_ID_DEFAULT);
4486 mDispatcher->notifyMotion(&upMotionArgs);
4487 // The first window gets nothing and the second gets up
4488 firstWindow->consumeMotionUp();
4489 secondWindow->assertNoEvents();
4490}
4491
Arthur Hungabbb9d82021-09-01 14:52:30 +00004492// This case will create two windows and one mirrored window on the default display and mirror
4493// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4494// the windows info of second display before default display.
4495TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4496 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4497 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004498 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004499 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004500 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004501 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004502 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004503
4504 sp<FakeWindowHandle> mirrorWindowInPrimary =
4505 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4506 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004507
4508 sp<FakeWindowHandle> firstWindowInSecondary =
4509 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4510 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004511
4512 sp<FakeWindowHandle> secondWindowInSecondary =
4513 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4514 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004515
4516 // Update window info, let it find window handle of second display first.
4517 mDispatcher->setInputWindows(
4518 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4519 {ADISPLAY_ID_DEFAULT,
4520 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4521
4522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4523 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4524 {50, 50}))
4525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4526
4527 // Window should receive motion event.
4528 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4529
4530 // Transfer touch focus
4531 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4532 secondWindowInPrimary->getToken()));
4533 // The first window gets cancel.
4534 firstWindowInPrimary->consumeMotionCancel();
4535 secondWindowInPrimary->consumeMotionDown();
4536
4537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4538 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4539 ADISPLAY_ID_DEFAULT, {150, 50}))
4540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4541 firstWindowInPrimary->assertNoEvents();
4542 secondWindowInPrimary->consumeMotionMove();
4543
4544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4545 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4546 {150, 50}))
4547 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4548 firstWindowInPrimary->assertNoEvents();
4549 secondWindowInPrimary->consumeMotionUp();
4550}
4551
4552// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4553// 'transferTouch' api.
4554TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4555 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4556 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004557 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004558 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004559 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004560 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004561 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004562
4563 sp<FakeWindowHandle> mirrorWindowInPrimary =
4564 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4565 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004566
4567 sp<FakeWindowHandle> firstWindowInSecondary =
4568 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4569 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004570
4571 sp<FakeWindowHandle> secondWindowInSecondary =
4572 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4573 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004574
4575 // Update window info, let it find window handle of second display first.
4576 mDispatcher->setInputWindows(
4577 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4578 {ADISPLAY_ID_DEFAULT,
4579 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4580
4581 // Touch on second display.
4582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4583 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4585
4586 // Window should receive motion event.
4587 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4588
4589 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004590 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004591
4592 // The first window gets cancel.
4593 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4594 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4595
4596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4597 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4598 SECOND_DISPLAY_ID, {150, 50}))
4599 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4600 firstWindowInPrimary->assertNoEvents();
4601 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4602
4603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4604 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4606 firstWindowInPrimary->assertNoEvents();
4607 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4608}
4609
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004610TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004611 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004612 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4613 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004614
Vishnu Nair47074b82020-08-14 11:54:47 -07004615 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004617 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004618
4619 window->consumeFocusEvent(true);
4620
4621 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4622 mDispatcher->notifyKey(&keyArgs);
4623
4624 // Window should receive key down event.
4625 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4626}
4627
4628TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4631 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004632
Arthur Hung72d8dc32020-03-28 00:48:39 +00004633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004634
4635 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4636 mDispatcher->notifyKey(&keyArgs);
4637 mDispatcher->waitForIdle();
4638
4639 window->assertNoEvents();
4640}
4641
4642// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4643TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004645 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4646 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004647
Arthur Hung72d8dc32020-03-28 00:48:39 +00004648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004649
4650 // Send key
4651 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4652 mDispatcher->notifyKey(&keyArgs);
4653 // Send motion
4654 NotifyMotionArgs motionArgs =
4655 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4656 ADISPLAY_ID_DEFAULT);
4657 mDispatcher->notifyMotion(&motionArgs);
4658
4659 // Window should receive only the motion event
4660 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4661 window->assertNoEvents(); // Key event or focus event will not be received
4662}
4663
arthurhungea3f4fc2020-12-21 23:18:53 +08004664TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4666
arthurhungea3f4fc2020-12-21 23:18:53 +08004667 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004668 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4669 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004670 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004671
arthurhungea3f4fc2020-12-21 23:18:53 +08004672 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004673 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4674 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004675 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004676
4677 // Add the windows to the dispatcher
4678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4679
4680 PointF pointInFirst = {300, 200};
4681 PointF pointInSecond = {300, 600};
4682
4683 // Send down to the first window
4684 NotifyMotionArgs firstDownMotionArgs =
4685 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4686 ADISPLAY_ID_DEFAULT, {pointInFirst});
4687 mDispatcher->notifyMotion(&firstDownMotionArgs);
4688 // Only the first window should get the down event
4689 firstWindow->consumeMotionDown();
4690 secondWindow->assertNoEvents();
4691
4692 // Send down to the second window
4693 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004694 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004695 {pointInFirst, pointInSecond});
4696 mDispatcher->notifyMotion(&secondDownMotionArgs);
4697 // The first window gets a move and the second a down
4698 firstWindow->consumeMotionMove();
4699 secondWindow->consumeMotionDown();
4700
4701 // Send pointer cancel to the second window
4702 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004703 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004704 {pointInFirst, pointInSecond});
4705 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
4706 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4707 // The first window gets move and the second gets cancel.
4708 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4709 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4710
4711 // Send up event.
4712 NotifyMotionArgs upMotionArgs =
4713 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4714 ADISPLAY_ID_DEFAULT);
4715 mDispatcher->notifyMotion(&upMotionArgs);
4716 // The first window gets up and the second gets nothing.
4717 firstWindow->consumeMotionUp();
4718 secondWindow->assertNoEvents();
4719}
4720
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004721TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4723
4724 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004725 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4727 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4728 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4729 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4730
Harry Cutts33476232023-01-30 19:57:29 +00004731 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004732 window->assertNoEvents();
4733 mDispatcher->waitForIdle();
4734}
4735
chaviwd1c23182019-12-20 18:44:56 -08004736class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004737public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004738 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004739 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004740 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004741 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004742 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004743 }
4744
chaviwd1c23182019-12-20 18:44:56 -08004745 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4746
4747 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004748 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4749 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004750 }
4751
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004752 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4753
4754 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4755
chaviwd1c23182019-12-20 18:44:56 -08004756 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004757 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004758 expectedDisplayId, expectedFlags);
4759 }
4760
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004761 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004762 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004763 expectedDisplayId, expectedFlags);
4764 }
4765
chaviwd1c23182019-12-20 18:44:56 -08004766 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004767 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004768 expectedDisplayId, expectedFlags);
4769 }
4770
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004771 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004772 mInputReceiver->consumeMotionEvent(
4773 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4774 WithDisplayId(expectedDisplayId),
4775 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004776 }
4777
Arthur Hungfbfa5722021-11-16 02:45:54 +00004778 void consumeMotionPointerDown(int32_t pointerIdx) {
4779 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4780 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004781 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004782 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004783 }
4784
Evan Rosky84f07f02021-04-16 10:42:42 -07004785 MotionEvent* consumeMotion() {
4786 InputEvent* event = mInputReceiver->consume();
4787 if (!event) {
4788 ADD_FAILURE() << "No event was produced";
4789 return nullptr;
4790 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004791 if (event->getType() != InputEventType::MOTION) {
4792 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004793 return nullptr;
4794 }
4795 return static_cast<MotionEvent*>(event);
4796 }
4797
chaviwd1c23182019-12-20 18:44:56 -08004798 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4799
4800private:
4801 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004802};
4803
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004804using InputDispatcherMonitorTest = InputDispatcherTest;
4805
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004806/**
4807 * Two entities that receive touch: A window, and a global monitor.
4808 * The touch goes to the window, and then the window disappears.
4809 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4810 * for the monitor, as well.
4811 * 1. foregroundWindow
4812 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4813 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004814TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4816 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004817 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004818
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004819 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004820
4821 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4823 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4824 {100, 200}))
4825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4826
4827 // Both the foreground window and the global monitor should receive the touch down
4828 window->consumeMotionDown();
4829 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4830
4831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4832 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4833 ADISPLAY_ID_DEFAULT, {110, 200}))
4834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4835
4836 window->consumeMotionMove();
4837 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4838
4839 // Now the foreground window goes away
4840 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4841 window->consumeMotionCancel();
4842 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4843
4844 // If more events come in, there will be no more foreground window to send them to. This will
4845 // cause a cancel for the monitor, as well.
4846 ASSERT_EQ(InputEventInjectionResult::FAILED,
4847 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4848 ADISPLAY_ID_DEFAULT, {120, 200}))
4849 << "Injection should fail because the window was removed";
4850 window->assertNoEvents();
4851 // Global monitor now gets the cancel
4852 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4853}
4854
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004855TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004857 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4858 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004860
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004861 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004862
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004864 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004866 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004867 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004868}
4869
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004870TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4871 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004872
Chris Yea209fde2020-07-22 13:54:51 -07004873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4875 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004876 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004877
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004879 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004881 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004882 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004883
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004884 // Pilfer pointers from the monitor.
4885 // This should not do anything and the window should continue to receive events.
4886 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004887
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004889 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4890 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004892
4893 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4894 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004895}
4896
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004897TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004899 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4900 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004901 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4902 window->setWindowOffset(20, 40);
4903 window->setWindowTransform(0, 1, -1, 0);
4904
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004905 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004906
4907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4908 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4910 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4911 MotionEvent* event = monitor.consumeMotion();
4912 // Even though window has transform, gesture monitor must not.
4913 ASSERT_EQ(ui::Transform(), event->getTransform());
4914}
4915
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004916TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004917 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004918 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004919
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004920 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004921 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004922 << "Injection should fail if there is a monitor, but no touchable window";
4923 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004924}
4925
chaviw81e2bb92019-12-18 15:03:51 -08004926TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004928 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4929 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004930
Arthur Hung72d8dc32020-03-28 00:48:39 +00004931 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004932
4933 NotifyMotionArgs motionArgs =
4934 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4935 ADISPLAY_ID_DEFAULT);
4936
4937 mDispatcher->notifyMotion(&motionArgs);
4938 // Window should receive motion down event.
4939 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4940
4941 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004942 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004943 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4944 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4945 motionArgs.pointerCoords[0].getX() - 10);
4946
4947 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004948 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004949 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004950}
4951
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004952/**
4953 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
4954 * the device default right away. In the test scenario, we check both the default value,
4955 * and the action of enabling / disabling.
4956 */
4957TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07004958 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004959 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4960 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08004961 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004962
4963 // Set focused application.
4964 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004965 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004966
4967 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00004968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004969 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004970 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004971
4972 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004973 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004974 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004975 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004976
4977 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004978 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004979 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004980 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07004981 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004983 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004984 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004985
4986 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004987 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004989 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004990
4991 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004992 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004993 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004994 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07004995 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004997 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004998 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004999
5000 window->assertNoEvents();
5001}
5002
Gang Wange9087892020-01-07 12:17:14 -05005003TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005005 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5006 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005007
5008 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005009 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005010
Arthur Hung72d8dc32020-03-28 00:48:39 +00005011 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005012 setFocusedWindow(window);
5013
Harry Cutts33476232023-01-30 19:57:29 +00005014 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005015
5016 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5017 mDispatcher->notifyKey(&keyArgs);
5018
5019 InputEvent* event = window->consume();
5020 ASSERT_NE(event, nullptr);
5021
5022 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5023 ASSERT_NE(verified, nullptr);
5024 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5025
5026 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5027 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5028 ASSERT_EQ(keyArgs.source, verified->source);
5029 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5030
5031 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5032
5033 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005034 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005035 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005036 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5037 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5038 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5039 ASSERT_EQ(0, verifiedKey.repeatCount);
5040}
5041
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005042TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005044 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5045 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005046
5047 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5048
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005049 ui::Transform transform;
5050 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5051
5052 gui::DisplayInfo displayInfo;
5053 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5054 displayInfo.transform = transform;
5055
5056 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005057
5058 NotifyMotionArgs motionArgs =
5059 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5060 ADISPLAY_ID_DEFAULT);
5061 mDispatcher->notifyMotion(&motionArgs);
5062
5063 InputEvent* event = window->consume();
5064 ASSERT_NE(event, nullptr);
5065
5066 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5067 ASSERT_NE(verified, nullptr);
5068 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5069
5070 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5071 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5072 EXPECT_EQ(motionArgs.source, verified->source);
5073 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5074
5075 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5076
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005077 const vec2 rawXY =
5078 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5079 motionArgs.pointerCoords[0].getXYValue());
5080 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5081 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005082 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005083 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005084 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005085 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5086 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5087}
5088
chaviw09c8d2d2020-08-24 15:48:26 -07005089/**
5090 * Ensure that separate calls to sign the same data are generating the same key.
5091 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5092 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5093 * tests.
5094 */
5095TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5096 KeyEvent event = getTestKeyEvent();
5097 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5098
5099 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5100 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5101 ASSERT_EQ(hmac1, hmac2);
5102}
5103
5104/**
5105 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5106 */
5107TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5108 KeyEvent event = getTestKeyEvent();
5109 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5110 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5111
5112 verifiedEvent.deviceId += 1;
5113 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5114
5115 verifiedEvent.source += 1;
5116 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5117
5118 verifiedEvent.eventTimeNanos += 1;
5119 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5120
5121 verifiedEvent.displayId += 1;
5122 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5123
5124 verifiedEvent.action += 1;
5125 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5126
5127 verifiedEvent.downTimeNanos += 1;
5128 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5129
5130 verifiedEvent.flags += 1;
5131 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5132
5133 verifiedEvent.keyCode += 1;
5134 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5135
5136 verifiedEvent.scanCode += 1;
5137 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5138
5139 verifiedEvent.metaState += 1;
5140 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5141
5142 verifiedEvent.repeatCount += 1;
5143 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5144}
5145
Vishnu Nair958da932020-08-21 17:12:37 -07005146TEST_F(InputDispatcherTest, SetFocusedWindow) {
5147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5148 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005149 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005150 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005151 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005152 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5153
5154 // Top window is also focusable but is not granted focus.
5155 windowTop->setFocusable(true);
5156 windowSecond->setFocusable(true);
5157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5158 setFocusedWindow(windowSecond);
5159
5160 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5162 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005163
5164 // Focused window should receive event.
5165 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5166 windowTop->assertNoEvents();
5167}
5168
5169TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5171 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005172 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5174
5175 window->setFocusable(true);
5176 // Release channel for window is no longer valid.
5177 window->releaseChannel();
5178 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5179 setFocusedWindow(window);
5180
5181 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005182 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5183 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005184
5185 // window channel is invalid, so it should not receive any input event.
5186 window->assertNoEvents();
5187}
5188
5189TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5191 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005192 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005193 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005194 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5195
Vishnu Nair958da932020-08-21 17:12:37 -07005196 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5197 setFocusedWindow(window);
5198
5199 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005200 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5201 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005202
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005203 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005204 window->assertNoEvents();
5205}
5206
5207TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5209 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005211 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005212 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005213 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5214
5215 windowTop->setFocusable(true);
5216 windowSecond->setFocusable(true);
5217 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5218 setFocusedWindow(windowTop);
5219 windowTop->consumeFocusEvent(true);
5220
Chavi Weingarten847e8512023-03-29 00:26:09 +00005221 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5222 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005223 windowSecond->consumeFocusEvent(true);
5224 windowTop->consumeFocusEvent(false);
5225
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5227 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005228
5229 // Focused window should receive event.
5230 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5231}
5232
Chavi Weingarten847e8512023-03-29 00:26:09 +00005233TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5235 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005236 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005237 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005238 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005239 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5240
5241 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005242 windowSecond->setFocusable(false);
5243 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005244 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005245 setFocusedWindow(windowTop);
5246 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005247
Chavi Weingarten847e8512023-03-29 00:26:09 +00005248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5249 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005250
5251 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005252 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005253 windowSecond->assertNoEvents();
5254}
5255
5256TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5258 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005259 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005260 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005261 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5262 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005263 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5264
5265 window->setFocusable(true);
5266 previousFocusedWindow->setFocusable(true);
5267 window->setVisible(false);
5268 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5269 setFocusedWindow(previousFocusedWindow);
5270 previousFocusedWindow->consumeFocusEvent(true);
5271
5272 // Requesting focus on invisible window takes focus from currently focused window.
5273 setFocusedWindow(window);
5274 previousFocusedWindow->consumeFocusEvent(false);
5275
5276 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005278 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5279 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005280
5281 // Window does not get focus event or key down.
5282 window->assertNoEvents();
5283
5284 // Window becomes visible.
5285 window->setVisible(true);
5286 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5287
5288 // Window receives focus event.
5289 window->consumeFocusEvent(true);
5290 // Focused window receives key down.
5291 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5292}
5293
Vishnu Nair599f1412021-06-21 10:39:58 -07005294TEST_F(InputDispatcherTest, DisplayRemoved) {
5295 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5296 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005297 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005298 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5299
5300 // window is granted focus.
5301 window->setFocusable(true);
5302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5303 setFocusedWindow(window);
5304 window->consumeFocusEvent(true);
5305
5306 // When a display is removed window loses focus.
5307 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5308 window->consumeFocusEvent(false);
5309}
5310
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005311/**
5312 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5313 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5314 * of the 'slipperyEnterWindow'.
5315 *
5316 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5317 * a way so that the touched location is no longer covered by the top window.
5318 *
5319 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5320 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5321 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5322 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5323 * with ACTION_DOWN).
5324 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5325 * window moved itself away from the touched location and had Flag::SLIPPERY.
5326 *
5327 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5328 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5329 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5330 *
5331 * In this test, we ensure that the event received by the bottom window has
5332 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5333 */
5334TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005335 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5336 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005337
5338 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5339 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5340
5341 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005342 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005343 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005344 // Make sure this one overlaps the bottom window
5345 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5346 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5347 // one. Windows with the same owner are not considered to be occluding each other.
5348 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5349
5350 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005351 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005352 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5353
5354 mDispatcher->setInputWindows(
5355 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5356
5357 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
5358 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5359 ADISPLAY_ID_DEFAULT, {{50, 50}});
5360 mDispatcher->notifyMotion(&args);
5361 slipperyExitWindow->consumeMotionDown();
5362 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5363 mDispatcher->setInputWindows(
5364 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5365
5366 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5367 ADISPLAY_ID_DEFAULT, {{51, 51}});
5368 mDispatcher->notifyMotion(&args);
5369
5370 slipperyExitWindow->consumeMotionCancel();
5371
5372 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5373 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5374}
5375
Garfield Tan1c7bc862020-01-28 13:24:04 -08005376class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5377protected:
5378 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5379 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5380
Chris Yea209fde2020-07-22 13:54:51 -07005381 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005382 sp<FakeWindowHandle> mWindow;
5383
5384 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005386 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005387 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005388 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5389 ASSERT_EQ(OK, mDispatcher->start());
5390
5391 setUpWindow();
5392 }
5393
5394 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005395 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005396 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005397
Vishnu Nair47074b82020-08-14 11:54:47 -07005398 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005399 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005400 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005401 mWindow->consumeFocusEvent(true);
5402 }
5403
Chris Ye2ad95392020-09-01 13:44:44 -07005404 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005405 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005406 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005407 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
5408 mDispatcher->notifyKey(&keyArgs);
5409
5410 // Window should receive key down event.
5411 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5412 }
5413
5414 void expectKeyRepeatOnce(int32_t repeatCount) {
5415 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5416 InputEvent* repeatEvent = mWindow->consume();
5417 ASSERT_NE(nullptr, repeatEvent);
5418
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005419 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005420
5421 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5422 uint32_t eventAction = repeatKeyEvent->getAction();
5423 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5424 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5425 }
5426
Chris Ye2ad95392020-09-01 13:44:44 -07005427 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005428 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005429 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005430 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
5431 mDispatcher->notifyKey(&keyArgs);
5432
5433 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005434 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005435 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005436 }
5437};
5438
5439TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005440 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005441 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5442 expectKeyRepeatOnce(repeatCount);
5443 }
5444}
5445
5446TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005447 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005448 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5449 expectKeyRepeatOnce(repeatCount);
5450 }
Harry Cutts33476232023-01-30 19:57:29 +00005451 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005452 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005453 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5454 expectKeyRepeatOnce(repeatCount);
5455 }
5456}
5457
5458TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005459 sendAndConsumeKeyDown(/*deviceId=*/1);
5460 expectKeyRepeatOnce(/*repeatCount=*/1);
5461 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005462 mWindow->assertNoEvents();
5463}
5464
5465TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005466 sendAndConsumeKeyDown(/*deviceId=*/1);
5467 expectKeyRepeatOnce(/*repeatCount=*/1);
5468 sendAndConsumeKeyDown(/*deviceId=*/2);
5469 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005470 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005471 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005472 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005473 expectKeyRepeatOnce(/*repeatCount=*/2);
5474 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005475 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005476 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005477 mWindow->assertNoEvents();
5478}
5479
5480TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005481 sendAndConsumeKeyDown(/*deviceId=*/1);
5482 expectKeyRepeatOnce(/*repeatCount=*/1);
5483 sendAndConsumeKeyDown(/*deviceId=*/2);
5484 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005485 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005486 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005487 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005488 mWindow->assertNoEvents();
5489}
5490
liushenxiang42232912021-05-21 20:24:09 +08005491TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5492 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005493 expectKeyRepeatOnce(/*repeatCount=*/1);
5494 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
liushenxiang42232912021-05-21 20:24:09 +08005495 mDispatcher->notifyDeviceReset(&args);
5496 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5497 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5498 mWindow->assertNoEvents();
5499}
5500
Garfield Tan1c7bc862020-01-28 13:24:04 -08005501TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005502 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005503 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005504 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5505 InputEvent* repeatEvent = mWindow->consume();
5506 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5507 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5508 IdGenerator::getSource(repeatEvent->getId()));
5509 }
5510}
5511
5512TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005513 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005514 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005515
5516 std::unordered_set<int32_t> idSet;
5517 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5518 InputEvent* repeatEvent = mWindow->consume();
5519 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5520 int32_t id = repeatEvent->getId();
5521 EXPECT_EQ(idSet.end(), idSet.find(id));
5522 idSet.insert(id);
5523 }
5524}
5525
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005526/* Test InputDispatcher for MultiDisplay */
5527class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5528public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005529 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005530 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005531
Chris Yea209fde2020-07-22 13:54:51 -07005532 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005533 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005534 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005535
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005536 // Set focus window for primary display, but focused display would be second one.
5537 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005538 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005539 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005540 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005541 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005542
Chris Yea209fde2020-07-22 13:54:51 -07005543 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005544 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005545 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005546 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005547 // Set focus display to second one.
5548 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5549 // Set focus window for second display.
5550 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005551 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005552 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005553 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005554 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005555 }
5556
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005557 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005558 InputDispatcherTest::TearDown();
5559
Chris Yea209fde2020-07-22 13:54:51 -07005560 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005561 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005562 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005563 windowInSecondary.clear();
5564 }
5565
5566protected:
Chris Yea209fde2020-07-22 13:54:51 -07005567 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005568 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005569 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005570 sp<FakeWindowHandle> windowInSecondary;
5571};
5572
5573TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5574 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5576 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5577 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005578 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005579 windowInSecondary->assertNoEvents();
5580
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005581 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5583 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005585 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005586 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005587}
5588
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005589TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005590 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5592 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005593 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005594 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005595 windowInSecondary->assertNoEvents();
5596
5597 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005599 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005600 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005601 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005602
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005603 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005604 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005605
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005606 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005607 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005608 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005609
5610 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005611 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005612 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005613 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005614 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005615 windowInSecondary->assertNoEvents();
5616}
5617
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005618// Test per-display input monitors for motion event.
5619TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005620 FakeMonitorReceiver monitorInPrimary =
5621 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5622 FakeMonitorReceiver monitorInSecondary =
5623 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005624
5625 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5627 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005629 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005630 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005631 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005632 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005633
5634 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5636 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005638 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005639 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005640 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005641 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005642
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005643 // Lift up the touch from the second display
5644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5645 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5647 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5648 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5649
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005650 // Test inject a non-pointer motion event.
5651 // If specific a display, it will dispatch to the focused window of particular display,
5652 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5654 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005656 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005657 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005658 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005659 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005660}
5661
5662// Test per-display input monitors for key event.
5663TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005664 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005665 FakeMonitorReceiver monitorInPrimary =
5666 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5667 FakeMonitorReceiver monitorInSecondary =
5668 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005669
5670 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5672 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005673 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005674 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005675 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005676 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005677}
5678
Vishnu Nair958da932020-08-21 17:12:37 -07005679TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5680 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005681 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005682 secondWindowInPrimary->setFocusable(true);
5683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5684 setFocusedWindow(secondWindowInPrimary);
5685 windowInPrimary->consumeFocusEvent(false);
5686 secondWindowInPrimary->consumeFocusEvent(true);
5687
5688 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5690 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005691 windowInPrimary->assertNoEvents();
5692 windowInSecondary->assertNoEvents();
5693 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5694}
5695
Arthur Hungdfd528e2021-12-08 13:23:04 +00005696TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5697 FakeMonitorReceiver monitorInPrimary =
5698 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5699 FakeMonitorReceiver monitorInSecondary =
5700 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5701
5702 // Test touch down on primary display.
5703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5704 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5706 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5707 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5708
5709 // Test touch down on second display.
5710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5711 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5713 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5714 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5715
5716 // Trigger cancel touch.
5717 mDispatcher->cancelCurrentTouch();
5718 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5719 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5720 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5721 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5722
5723 // Test inject a move motion event, no window/monitor should receive the event.
5724 ASSERT_EQ(InputEventInjectionResult::FAILED,
5725 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5726 ADISPLAY_ID_DEFAULT, {110, 200}))
5727 << "Inject motion event should return InputEventInjectionResult::FAILED";
5728 windowInPrimary->assertNoEvents();
5729 monitorInPrimary.assertNoEvents();
5730
5731 ASSERT_EQ(InputEventInjectionResult::FAILED,
5732 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5733 SECOND_DISPLAY_ID, {110, 200}))
5734 << "Inject motion event should return InputEventInjectionResult::FAILED";
5735 windowInSecondary->assertNoEvents();
5736 monitorInSecondary.assertNoEvents();
5737}
5738
Jackal Guof9696682018-10-05 12:23:23 +08005739class InputFilterTest : public InputDispatcherTest {
5740protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005741 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5742 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005743 NotifyMotionArgs motionArgs;
5744
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005745 motionArgs =
5746 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005747 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005748 motionArgs =
5749 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005750 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005751 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005752 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005753 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5754 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005755 } else {
5756 mFakePolicy->assertFilterInputEventWasNotCalled();
5757 }
5758 }
5759
5760 void testNotifyKey(bool expectToBeFiltered) {
5761 NotifyKeyArgs keyArgs;
5762
5763 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5764 mDispatcher->notifyKey(&keyArgs);
5765 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
5766 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005767 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005768
5769 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005770 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005771 } else {
5772 mFakePolicy->assertFilterInputEventWasNotCalled();
5773 }
5774 }
5775};
5776
5777// Test InputFilter for MotionEvent
5778TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5779 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5780 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5781 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5782
5783 // Enable InputFilter
5784 mDispatcher->setInputFilterEnabled(true);
5785 // Test touch on both primary and second display, and check if both events are filtered.
5786 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5787 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5788
5789 // Disable InputFilter
5790 mDispatcher->setInputFilterEnabled(false);
5791 // Test touch on both primary and second display, and check if both events aren't filtered.
5792 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5793 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5794}
5795
5796// Test InputFilter for KeyEvent
5797TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5798 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5799 testNotifyKey(/*expectToBeFiltered*/ false);
5800
5801 // Enable InputFilter
5802 mDispatcher->setInputFilterEnabled(true);
5803 // Send a key event, and check if it is filtered.
5804 testNotifyKey(/*expectToBeFiltered*/ true);
5805
5806 // Disable InputFilter
5807 mDispatcher->setInputFilterEnabled(false);
5808 // Send a key event, and check if it isn't filtered.
5809 testNotifyKey(/*expectToBeFiltered*/ false);
5810}
5811
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005812// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5813// logical display coordinate space.
5814TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5815 ui::Transform firstDisplayTransform;
5816 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5817 ui::Transform secondDisplayTransform;
5818 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5819
5820 std::vector<gui::DisplayInfo> displayInfos(2);
5821 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5822 displayInfos[0].transform = firstDisplayTransform;
5823 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5824 displayInfos[1].transform = secondDisplayTransform;
5825
5826 mDispatcher->onWindowInfosChanged({}, displayInfos);
5827
5828 // Enable InputFilter
5829 mDispatcher->setInputFilterEnabled(true);
5830
5831 // Ensure the correct transforms are used for the displays.
5832 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5833 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5834}
5835
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005836class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5837protected:
5838 virtual void SetUp() override {
5839 InputDispatcherTest::SetUp();
5840
5841 /**
5842 * We don't need to enable input filter to test the injected event policy, but we enabled it
5843 * here to make the tests more realistic, since this policy only matters when inputfilter is
5844 * on.
5845 */
5846 mDispatcher->setInputFilterEnabled(true);
5847
5848 std::shared_ptr<InputApplicationHandle> application =
5849 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005850 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5851 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005852
5853 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5854 mWindow->setFocusable(true);
5855 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5856 setFocusedWindow(mWindow);
5857 mWindow->consumeFocusEvent(true);
5858 }
5859
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005860 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5861 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005862 KeyEvent event;
5863
5864 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5865 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5866 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005867 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005868 const int32_t additionalPolicyFlags =
5869 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005871 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005872 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5873 policyFlags | additionalPolicyFlags));
5874
5875 InputEvent* received = mWindow->consume();
5876 ASSERT_NE(nullptr, received);
5877 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005878 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005879 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5880 ASSERT_EQ(flags, keyEvent.getFlags());
5881 }
5882
5883 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5884 int32_t flags) {
5885 MotionEvent event;
5886 PointerProperties pointerProperties[1];
5887 PointerCoords pointerCoords[1];
5888 pointerProperties[0].clear();
5889 pointerProperties[0].id = 0;
5890 pointerCoords[0].clear();
5891 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5892 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5893
5894 ui::Transform identityTransform;
5895 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5896 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5897 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5898 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5899 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005900 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005901 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005902 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5903
5904 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005906 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005907 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5908 policyFlags | additionalPolicyFlags));
5909
5910 InputEvent* received = mWindow->consume();
5911 ASSERT_NE(nullptr, received);
5912 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005913 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005914 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5915 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005916 }
5917
5918private:
5919 sp<FakeWindowHandle> mWindow;
5920};
5921
5922TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005923 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5924 // filter. Without it, the event will no different from a regularly injected event, and the
5925 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005926 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5927 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005928}
5929
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005930TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005931 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005932 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005933 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5934}
5935
5936TEST_F(InputFilterInjectionPolicyTest,
5937 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5938 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005939 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005940 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005941}
5942
5943TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005944 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5945 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005946}
5947
chaviwfd6d3512019-03-25 13:23:49 -07005948class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005949 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005950 InputDispatcherTest::SetUp();
5951
Chris Yea209fde2020-07-22 13:54:51 -07005952 std::shared_ptr<FakeApplicationHandle> application =
5953 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005954 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005955 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005956 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07005957
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005958 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005959 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005960 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07005961
5962 // Set focused application.
5963 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005964 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07005965
5966 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005967 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005968 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005969 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07005970 }
5971
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005972 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07005973 InputDispatcherTest::TearDown();
5974
5975 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005976 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07005977 }
5978
5979protected:
5980 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005981 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005982 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07005983};
5984
5985// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5986// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
5987// the onPointerDownOutsideFocus callback.
5988TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005990 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5991 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005993 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005994
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005995 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07005996 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
5997}
5998
5999// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6000// DOWN on the window that doesn't have focus. Ensure no window received the
6001// onPointerDownOutsideFocus callback.
6002TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006004 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006006 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006007
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006008 ASSERT_TRUE(mDispatcher->waitForIdle());
6009 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006010}
6011
6012// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6013// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6014TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6016 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006017 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006018 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006019
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006020 ASSERT_TRUE(mDispatcher->waitForIdle());
6021 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006022}
6023
6024// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6025// DOWN on the window that already has focus. Ensure no window received the
6026// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006027TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006029 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006030 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006032 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006033
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006034 ASSERT_TRUE(mDispatcher->waitForIdle());
6035 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006036}
6037
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006038// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6039// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6040TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6041 const MotionEvent event =
6042 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6043 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006044 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006045 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6046 .build();
6047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6048 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6049 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6050
6051 ASSERT_TRUE(mDispatcher->waitForIdle());
6052 mFakePolicy->assertOnPointerDownWasNotCalled();
6053 // Ensure that the unfocused window did not receive any FOCUS events.
6054 mUnfocusedWindow->assertNoEvents();
6055}
6056
chaviwaf87b3e2019-10-01 16:59:28 -07006057// These tests ensures we can send touch events to a single client when there are multiple input
6058// windows that point to the same client token.
6059class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6060 virtual void SetUp() override {
6061 InputDispatcherTest::SetUp();
6062
Chris Yea209fde2020-07-22 13:54:51 -07006063 std::shared_ptr<FakeApplicationHandle> application =
6064 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006065 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6066 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006067 mWindow1->setFrame(Rect(0, 0, 100, 100));
6068
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006069 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6070 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006071 mWindow2->setFrame(Rect(100, 100, 200, 200));
6072
Arthur Hung72d8dc32020-03-28 00:48:39 +00006073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006074 }
6075
6076protected:
6077 sp<FakeWindowHandle> mWindow1;
6078 sp<FakeWindowHandle> mWindow2;
6079
6080 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006081 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006082 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6083 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006084 }
6085
6086 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6087 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006088 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006089 InputEvent* event = window->consume();
6090
6091 ASSERT_NE(nullptr, event) << name.c_str()
6092 << ": consumer should have returned non-NULL event.";
6093
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006094 ASSERT_EQ(InputEventType::MOTION, event->getType())
6095 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006096
6097 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006098 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006099 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006100
6101 for (size_t i = 0; i < points.size(); i++) {
6102 float expectedX = points[i].x;
6103 float expectedY = points[i].y;
6104
6105 EXPECT_EQ(expectedX, motionEvent.getX(i))
6106 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6107 << ", got " << motionEvent.getX(i);
6108 EXPECT_EQ(expectedY, motionEvent.getY(i))
6109 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6110 << ", got " << motionEvent.getY(i);
6111 }
6112 }
chaviw9eaa22c2020-07-01 16:21:27 -07006113
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006114 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006115 std::vector<PointF> expectedPoints) {
6116 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6117 ADISPLAY_ID_DEFAULT, touchedPoints);
6118 mDispatcher->notifyMotion(&motionArgs);
6119
6120 // Always consume from window1 since it's the window that has the InputReceiver
6121 consumeMotionEvent(mWindow1, action, expectedPoints);
6122 }
chaviwaf87b3e2019-10-01 16:59:28 -07006123};
6124
6125TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6126 // Touch Window 1
6127 PointF touchedPoint = {10, 10};
6128 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006129 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006130
6131 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006132 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006133
6134 // Touch Window 2
6135 touchedPoint = {150, 150};
6136 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006137 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006138}
6139
chaviw9eaa22c2020-07-01 16:21:27 -07006140TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6141 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006142 mWindow2->setWindowScale(0.5f, 0.5f);
6143
6144 // Touch Window 1
6145 PointF touchedPoint = {10, 10};
6146 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006147 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006148 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006149 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006150
6151 // Touch Window 2
6152 touchedPoint = {150, 150};
6153 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006154 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6155 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006156
chaviw9eaa22c2020-07-01 16:21:27 -07006157 // Update the transform so rotation is set
6158 mWindow2->setWindowTransform(0, -1, 1, 0);
6159 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6160 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006161}
6162
chaviw9eaa22c2020-07-01 16:21:27 -07006163TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006164 mWindow2->setWindowScale(0.5f, 0.5f);
6165
6166 // Touch Window 1
6167 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6168 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006169 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006170
6171 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006172 touchedPoints.push_back(PointF{150, 150});
6173 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006174 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006175
chaviw9eaa22c2020-07-01 16:21:27 -07006176 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006177 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006178 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006179
chaviw9eaa22c2020-07-01 16:21:27 -07006180 // Update the transform so rotation is set for Window 2
6181 mWindow2->setWindowTransform(0, -1, 1, 0);
6182 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006183 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006184}
6185
chaviw9eaa22c2020-07-01 16:21:27 -07006186TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006187 mWindow2->setWindowScale(0.5f, 0.5f);
6188
6189 // Touch Window 1
6190 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6191 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006192 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006193
6194 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006195 touchedPoints.push_back(PointF{150, 150});
6196 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006197
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006198 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006199
6200 // Move both windows
6201 touchedPoints = {{20, 20}, {175, 175}};
6202 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6203 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6204
chaviw9eaa22c2020-07-01 16:21:27 -07006205 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006206
chaviw9eaa22c2020-07-01 16:21:27 -07006207 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006208 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006209 expectedPoints.pop_back();
6210
6211 // Touch Window 2
6212 mWindow2->setWindowTransform(0, -1, 1, 0);
6213 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006214 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006215
6216 // Move both windows
6217 touchedPoints = {{20, 20}, {175, 175}};
6218 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6219 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6220
6221 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006222}
6223
6224TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6225 mWindow1->setWindowScale(0.5f, 0.5f);
6226
6227 // Touch Window 1
6228 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6229 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006230 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006231
6232 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006233 touchedPoints.push_back(PointF{150, 150});
6234 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006235
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006236 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006237
6238 // Move both windows
6239 touchedPoints = {{20, 20}, {175, 175}};
6240 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6241 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6242
chaviw9eaa22c2020-07-01 16:21:27 -07006243 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006244}
6245
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006246class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6247 virtual void SetUp() override {
6248 InputDispatcherTest::SetUp();
6249
Chris Yea209fde2020-07-22 13:54:51 -07006250 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006251 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006252 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6253 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006254 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006255 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006256 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006257
6258 // Set focused application.
6259 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6260
6261 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006262 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006263 mWindow->consumeFocusEvent(true);
6264 }
6265
6266 virtual void TearDown() override {
6267 InputDispatcherTest::TearDown();
6268 mWindow.clear();
6269 }
6270
6271protected:
Chris Yea209fde2020-07-22 13:54:51 -07006272 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006273 sp<FakeWindowHandle> mWindow;
6274 static constexpr PointF WINDOW_LOCATION = {20, 20};
6275
6276 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006278 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6279 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006281 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6282 WINDOW_LOCATION));
6283 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006284
6285 sp<FakeWindowHandle> addSpyWindow() {
6286 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006287 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006288 spy->setTrustedOverlay(true);
6289 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006290 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006291 spy->setDispatchingTimeout(30ms);
6292 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6293 return spy;
6294 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006295};
6296
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006297// Send a tap and respond, which should not cause an ANR.
6298TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6299 tapOnWindow();
6300 mWindow->consumeMotionDown();
6301 mWindow->consumeMotionUp();
6302 ASSERT_TRUE(mDispatcher->waitForIdle());
6303 mFakePolicy->assertNotifyAnrWasNotCalled();
6304}
6305
6306// Send a regular key and respond, which should not cause an ANR.
6307TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006309 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6310 ASSERT_TRUE(mDispatcher->waitForIdle());
6311 mFakePolicy->assertNotifyAnrWasNotCalled();
6312}
6313
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006314TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6315 mWindow->setFocusable(false);
6316 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6317 mWindow->consumeFocusEvent(false);
6318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006319 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006320 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6321 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6322 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006324 // Key will not go to window because we have no focused window.
6325 // The 'no focused window' ANR timer should start instead.
6326
6327 // Now, the focused application goes away.
6328 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6329 // The key should get dropped and there should be no ANR.
6330
6331 ASSERT_TRUE(mDispatcher->waitForIdle());
6332 mFakePolicy->assertNotifyAnrWasNotCalled();
6333}
6334
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006335// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006336// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6337// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006338TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006340 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6341 WINDOW_LOCATION));
6342
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006343 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6344 ASSERT_TRUE(sequenceNum);
6345 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006346 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006347
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006348 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006349 mWindow->consumeMotionEvent(
6350 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006351 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006352 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006353}
6354
6355// Send a key to the app and have the app not respond right away.
6356TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6357 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006359 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6360 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006361 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006362 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006363 ASSERT_TRUE(mDispatcher->waitForIdle());
6364}
6365
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006366// We have a focused application, but no focused window
6367TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006368 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006369 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6370 mWindow->consumeFocusEvent(false);
6371
6372 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006374 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6375 WINDOW_LOCATION));
6376 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6377 mDispatcher->waitForIdle();
6378 mFakePolicy->assertNotifyAnrWasNotCalled();
6379
6380 // Once a focused event arrives, we get an ANR for this application
6381 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6382 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006383 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006384 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6385 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006386 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006387 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006388 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006389 ASSERT_TRUE(mDispatcher->waitForIdle());
6390}
6391
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006392/**
6393 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6394 * there will not be an ANR.
6395 */
6396TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6397 mWindow->setFocusable(false);
6398 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6399 mWindow->consumeFocusEvent(false);
6400
6401 KeyEvent event;
6402 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6403 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6404
6405 // Define a valid key down event that is stale (too old).
6406 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6407 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006408 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006409
6410 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6411
6412 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006413 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006414 InputEventInjectionSync::WAIT_FOR_RESULT,
6415 INJECT_EVENT_TIMEOUT, policyFlags);
6416 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6417 << "Injection should fail because the event is stale";
6418
6419 ASSERT_TRUE(mDispatcher->waitForIdle());
6420 mFakePolicy->assertNotifyAnrWasNotCalled();
6421 mWindow->assertNoEvents();
6422}
6423
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006424// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006425// Make sure that we don't notify policy twice about the same ANR.
6426TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006427 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006428 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6429 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006430
6431 // Once a focused event arrives, we get an ANR for this application
6432 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6433 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006434 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006435 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6436 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006437 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006438 const std::chrono::duration appTimeout =
6439 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6440 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006441
Vishnu Naire4df8752022-09-08 09:17:55 -07006442 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006443 // ANR should not be raised again. It is up to policy to do that if it desires.
6444 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006445
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006446 // If we now get a focused window, the ANR should stop, but the policy handles that via
6447 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006448 ASSERT_TRUE(mDispatcher->waitForIdle());
6449}
6450
6451// We have a focused application, but no focused window
6452TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006453 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006454 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6455 mWindow->consumeFocusEvent(false);
6456
6457 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006458 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006459 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006460 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6461 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006462
Vishnu Naire4df8752022-09-08 09:17:55 -07006463 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6464 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006465
6466 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006467 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006468 ASSERT_TRUE(mDispatcher->waitForIdle());
6469 mWindow->assertNoEvents();
6470}
6471
6472/**
6473 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6474 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6475 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6476 * the ANR mechanism should still work.
6477 *
6478 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6479 * DOWN event, while not responding on the second one.
6480 */
6481TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6482 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6483 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6484 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6485 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6486 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006487 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006488
6489 // Now send ACTION_UP, with identical timestamp
6490 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6491 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6492 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6493 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006494 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006495
6496 // We have now sent down and up. Let's consume first event and then ANR on the second.
6497 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6498 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006499 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006500}
6501
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006502// A spy window can receive an ANR
6503TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6504 sp<FakeWindowHandle> spy = addSpyWindow();
6505
6506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6507 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6508 WINDOW_LOCATION));
6509 mWindow->consumeMotionDown();
6510
6511 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6512 ASSERT_TRUE(sequenceNum);
6513 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006514 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006515
6516 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006517 spy->consumeMotionEvent(
6518 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006519 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006520 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006521}
6522
6523// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006524// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006525TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6526 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006527
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6529 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006530 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006532
6533 // Stuck on the ACTION_UP
6534 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006535 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006536
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006537 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006538 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006539 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6540 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006541
6542 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6543 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006544 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006545 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006546 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006547}
6548
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006549// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006550// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006551TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6552 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006553
6554 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006555 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6556 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006557
6558 mWindow->consumeMotionDown();
6559 // Stuck on the ACTION_UP
6560 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006561 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006562
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006563 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006564 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006565 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6566 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006567
6568 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6569 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006570 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006571 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006572 spy->assertNoEvents();
6573}
6574
6575TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6576 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6577
6578 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6579
6580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6581 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6582 WINDOW_LOCATION));
6583
6584 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6585 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6586 ASSERT_TRUE(consumeSeq);
6587
Prabir Pradhanedd96402022-02-15 01:46:16 -08006588 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006589
6590 monitor.finishEvent(*consumeSeq);
6591 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6592
6593 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006594 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006595}
6596
6597// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6598// process events, you don't get an anr. When the window later becomes unresponsive again, you
6599// get an ANR again.
6600// 1. tap -> block on ACTION_UP -> receive ANR
6601// 2. consume all pending events (= queue becomes healthy again)
6602// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6603TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6604 tapOnWindow();
6605
6606 mWindow->consumeMotionDown();
6607 // Block on ACTION_UP
6608 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006609 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006610 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6611 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006612 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006613 mWindow->assertNoEvents();
6614
6615 tapOnWindow();
6616 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006617 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006618 mWindow->consumeMotionUp();
6619
6620 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006621 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006622 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006623 mWindow->assertNoEvents();
6624}
6625
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006626// If a connection remains unresponsive for a while, make sure policy is only notified once about
6627// it.
6628TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006630 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6631 WINDOW_LOCATION));
6632
6633 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006634 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006635 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006636 // 'notifyConnectionUnresponsive' should only be called once per connection
6637 mFakePolicy->assertNotifyAnrWasNotCalled();
6638 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006639 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006640 mWindow->consumeMotionEvent(
6641 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006642 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006643 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006644 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006645 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006646}
6647
6648/**
6649 * If a window is processing a motion event, and then a key event comes in, the key event should
6650 * not to to the focused window until the motion is processed.
6651 *
6652 * Warning!!!
6653 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6654 * and the injection timeout that we specify when injecting the key.
6655 * We must have the injection timeout (10ms) be smaller than
6656 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6657 *
6658 * If that value changes, this test should also change.
6659 */
6660TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6661 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6663
6664 tapOnWindow();
6665 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6666 ASSERT_TRUE(downSequenceNum);
6667 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6668 ASSERT_TRUE(upSequenceNum);
6669 // Don't finish the events yet, and send a key
6670 // Injection will "succeed" because we will eventually give up and send the key to the focused
6671 // window even if motions are still being processed. But because the injection timeout is short,
6672 // we will receive INJECTION_TIMED_OUT as the result.
6673
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006674 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006675 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006676 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6677 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006678 // Key will not be sent to the window, yet, because the window is still processing events
6679 // and the key remains pending, waiting for the touch events to be processed
6680 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6681 ASSERT_FALSE(keySequenceNum);
6682
6683 std::this_thread::sleep_for(500ms);
6684 // if we wait long enough though, dispatcher will give up, and still send the key
6685 // to the focused window, even though we have not yet finished the motion event
6686 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6687 mWindow->finishEvent(*downSequenceNum);
6688 mWindow->finishEvent(*upSequenceNum);
6689}
6690
6691/**
6692 * If a window is processing a motion event, and then a key event comes in, the key event should
6693 * not go to the focused window until the motion is processed.
6694 * If then a new motion comes in, then the pending key event should be going to the currently
6695 * focused window right away.
6696 */
6697TEST_F(InputDispatcherSingleWindowAnr,
6698 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6699 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6701
6702 tapOnWindow();
6703 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6704 ASSERT_TRUE(downSequenceNum);
6705 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6706 ASSERT_TRUE(upSequenceNum);
6707 // Don't finish the events yet, and send a key
6708 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006710 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6711 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006712 // At this point, key is still pending, and should not be sent to the application yet.
6713 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6714 ASSERT_FALSE(keySequenceNum);
6715
6716 // Now tap down again. It should cause the pending key to go to the focused window right away.
6717 tapOnWindow();
6718 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6719 // the other events yet. We can finish events in any order.
6720 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6721 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6722 mWindow->consumeMotionDown();
6723 mWindow->consumeMotionUp();
6724 mWindow->assertNoEvents();
6725}
6726
6727class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6728 virtual void SetUp() override {
6729 InputDispatcherTest::SetUp();
6730
Chris Yea209fde2020-07-22 13:54:51 -07006731 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006732 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006733 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6734 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006735 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006736 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006737 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006738
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006739 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6740 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006741 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006742 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006743
6744 // Set focused application.
6745 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006746 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006747
6748 // Expect one focus window exist in display.
6749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006750 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006751 mFocusedWindow->consumeFocusEvent(true);
6752 }
6753
6754 virtual void TearDown() override {
6755 InputDispatcherTest::TearDown();
6756
6757 mUnfocusedWindow.clear();
6758 mFocusedWindow.clear();
6759 }
6760
6761protected:
Chris Yea209fde2020-07-22 13:54:51 -07006762 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006763 sp<FakeWindowHandle> mUnfocusedWindow;
6764 sp<FakeWindowHandle> mFocusedWindow;
6765 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6766 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6767 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6768
6769 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6770
6771 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6772
6773private:
6774 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006776 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6777 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006779 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6780 location));
6781 }
6782};
6783
6784// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6785// should be ANR'd first.
6786TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006788 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6789 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006791 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006792 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006793 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006794 // We consumed all events, so no ANR
6795 ASSERT_TRUE(mDispatcher->waitForIdle());
6796 mFakePolicy->assertNotifyAnrWasNotCalled();
6797
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6800 FOCUSED_WINDOW_LOCATION));
6801 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6802 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006803
6804 const std::chrono::duration timeout =
6805 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006806 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006807 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6808 // sequence to make it consistent
6809 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006810 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006811 mFocusedWindow->consumeMotionDown();
6812 // This cancel is generated because the connection was unresponsive
6813 mFocusedWindow->consumeMotionCancel();
6814 mFocusedWindow->assertNoEvents();
6815 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006816 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006817 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6818 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006819 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006820}
6821
6822// If we have 2 windows with identical timeouts that are both unresponsive,
6823// it doesn't matter which order they should have ANR.
6824// But we should receive ANR for both.
6825TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6826 // Set the timeout for unfocused window to match the focused window
6827 mUnfocusedWindow->setDispatchingTimeout(10ms);
6828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6829
6830 tapOnFocusedWindow();
6831 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006832 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6833 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6834 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006835
6836 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006837 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6838 mFocusedWindow->getToken() == anrConnectionToken2);
6839 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6840 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006841
6842 ASSERT_TRUE(mDispatcher->waitForIdle());
6843 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006844
6845 mFocusedWindow->consumeMotionDown();
6846 mFocusedWindow->consumeMotionUp();
6847 mUnfocusedWindow->consumeMotionOutside();
6848
Prabir Pradhanedd96402022-02-15 01:46:16 -08006849 sp<IBinder> responsiveToken1, responsiveToken2;
6850 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6851 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006852
6853 // Both applications should be marked as responsive, in any order
6854 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6855 mFocusedWindow->getToken() == responsiveToken2);
6856 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6857 mUnfocusedWindow->getToken() == responsiveToken2);
6858 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859}
6860
6861// If a window is already not responding, the second tap on the same window should be ignored.
6862// We should also log an error to account for the dropped event (not tested here).
6863// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6864TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6865 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006866 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006867 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006868 // Receive the events, but don't respond
6869 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6870 ASSERT_TRUE(downEventSequenceNum);
6871 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6872 ASSERT_TRUE(upEventSequenceNum);
6873 const std::chrono::duration timeout =
6874 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006875 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006876
6877 // Tap once again
6878 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006879 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006880 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6881 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006882 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006883 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6884 FOCUSED_WINDOW_LOCATION));
6885 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6886 // valid touch target
6887 mUnfocusedWindow->assertNoEvents();
6888
6889 // Consume the first tap
6890 mFocusedWindow->finishEvent(*downEventSequenceNum);
6891 mFocusedWindow->finishEvent(*upEventSequenceNum);
6892 ASSERT_TRUE(mDispatcher->waitForIdle());
6893 // The second tap did not go to the focused window
6894 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006895 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006896 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6897 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006898 mFakePolicy->assertNotifyAnrWasNotCalled();
6899}
6900
6901// If you tap outside of all windows, there will not be ANR
6902TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006903 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006904 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6905 LOCATION_OUTSIDE_ALL_WINDOWS));
6906 ASSERT_TRUE(mDispatcher->waitForIdle());
6907 mFakePolicy->assertNotifyAnrWasNotCalled();
6908}
6909
6910// Since the focused window is paused, tapping on it should not produce any events
6911TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6912 mFocusedWindow->setPaused(true);
6913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6914
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006915 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006916 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6917 FOCUSED_WINDOW_LOCATION));
6918
6919 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6920 ASSERT_TRUE(mDispatcher->waitForIdle());
6921 // Should not ANR because the window is paused, and touches shouldn't go to it
6922 mFakePolicy->assertNotifyAnrWasNotCalled();
6923
6924 mFocusedWindow->assertNoEvents();
6925 mUnfocusedWindow->assertNoEvents();
6926}
6927
6928/**
6929 * If a window is processing a motion event, and then a key event comes in, the key event should
6930 * not to to the focused window until the motion is processed.
6931 * If a different window becomes focused at this time, the key should go to that window instead.
6932 *
6933 * Warning!!!
6934 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6935 * and the injection timeout that we specify when injecting the key.
6936 * We must have the injection timeout (10ms) be smaller than
6937 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6938 *
6939 * If that value changes, this test should also change.
6940 */
6941TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
6942 // Set a long ANR timeout to prevent it from triggering
6943 mFocusedWindow->setDispatchingTimeout(2s);
6944 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6945
6946 tapOnUnfocusedWindow();
6947 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
6948 ASSERT_TRUE(downSequenceNum);
6949 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
6950 ASSERT_TRUE(upSequenceNum);
6951 // Don't finish the events yet, and send a key
6952 // Injection will succeed because we will eventually give up and send the key to the focused
6953 // window even if motions are still being processed.
6954
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006955 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006956 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6957 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006959 // Key will not be sent to the window, yet, because the window is still processing events
6960 // and the key remains pending, waiting for the touch events to be processed
6961 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
6962 ASSERT_FALSE(keySequenceNum);
6963
6964 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07006965 mFocusedWindow->setFocusable(false);
6966 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006967 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006968 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006969
6970 // Focus events should precede the key events
6971 mUnfocusedWindow->consumeFocusEvent(true);
6972 mFocusedWindow->consumeFocusEvent(false);
6973
6974 // Finish the tap events, which should unblock dispatcher
6975 mUnfocusedWindow->finishEvent(*downSequenceNum);
6976 mUnfocusedWindow->finishEvent(*upSequenceNum);
6977
6978 // Now that all queues are cleared and no backlog in the connections, the key event
6979 // can finally go to the newly focused "mUnfocusedWindow".
6980 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6981 mFocusedWindow->assertNoEvents();
6982 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006983 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984}
6985
6986// When the touch stream is split across 2 windows, and one of them does not respond,
6987// then ANR should be raised and the touch should be canceled for the unresponsive window.
6988// The other window should not be affected by that.
6989TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
6990 // Touch Window 1
6991 NotifyMotionArgs motionArgs =
6992 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6993 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
6994 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006995 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006996 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006997
6998 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006999 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7000 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007001 mDispatcher->notifyMotion(&motionArgs);
7002
7003 const std::chrono::duration timeout =
7004 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007005 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007006
7007 mUnfocusedWindow->consumeMotionDown();
7008 mFocusedWindow->consumeMotionDown();
7009 // Focused window may or may not receive ACTION_MOVE
7010 // But it should definitely receive ACTION_CANCEL due to the ANR
7011 InputEvent* event;
7012 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7013 ASSERT_TRUE(moveOrCancelSequenceNum);
7014 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7015 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007016 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007017 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7018 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7019 mFocusedWindow->consumeMotionCancel();
7020 } else {
7021 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7022 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007023 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007024 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7025 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007026
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007027 mUnfocusedWindow->assertNoEvents();
7028 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007029 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007030}
7031
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007032/**
7033 * If we have no focused window, and a key comes in, we start the ANR timer.
7034 * The focused application should add a focused window before the timer runs out to prevent ANR.
7035 *
7036 * If the user touches another application during this time, the key should be dropped.
7037 * Next, if a new focused window comes in, without toggling the focused application,
7038 * then no ANR should occur.
7039 *
7040 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7041 * but in some cases the policy may not update the focused application.
7042 */
7043TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7044 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7045 std::make_shared<FakeApplicationHandle>();
7046 focusedApplication->setDispatchingTimeout(60ms);
7047 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7048 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7049 mFocusedWindow->setFocusable(false);
7050
7051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7052 mFocusedWindow->consumeFocusEvent(false);
7053
7054 // Send a key. The ANR timer should start because there is no focused window.
7055 // 'focusedApplication' will get blamed if this timer completes.
7056 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007057 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007058 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7059 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7060 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007062
7063 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7064 // then the injected touches won't cause the focused event to get dropped.
7065 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7066 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7067 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7068 // For this test, it means that the key would get delivered to the window once it becomes
7069 // focused.
7070 std::this_thread::sleep_for(10ms);
7071
7072 // Touch unfocused window. This should force the pending key to get dropped.
7073 NotifyMotionArgs motionArgs =
7074 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7075 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
7076 mDispatcher->notifyMotion(&motionArgs);
7077
7078 // We do not consume the motion right away, because that would require dispatcher to first
7079 // process (== drop) the key event, and by that time, ANR will be raised.
7080 // Set the focused window first.
7081 mFocusedWindow->setFocusable(true);
7082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7083 setFocusedWindow(mFocusedWindow);
7084 mFocusedWindow->consumeFocusEvent(true);
7085 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7086 // to another application. This could be a bug / behaviour in the policy.
7087
7088 mUnfocusedWindow->consumeMotionDown();
7089
7090 ASSERT_TRUE(mDispatcher->waitForIdle());
7091 // Should not ANR because we actually have a focused window. It was just added too slowly.
7092 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7093}
7094
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007095// These tests ensure we cannot send touch events to a window that's positioned behind a window
7096// that has feature NO_INPUT_CHANNEL.
7097// Layout:
7098// Top (closest to user)
7099// mNoInputWindow (above all windows)
7100// mBottomWindow
7101// Bottom (furthest from user)
7102class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7103 virtual void SetUp() override {
7104 InputDispatcherTest::SetUp();
7105
7106 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007107 mNoInputWindow =
7108 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7109 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007110 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007111 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007112 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7113 // It's perfectly valid for this window to not have an associated input channel
7114
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007115 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7116 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007117 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7118
7119 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7120 }
7121
7122protected:
7123 std::shared_ptr<FakeApplicationHandle> mApplication;
7124 sp<FakeWindowHandle> mNoInputWindow;
7125 sp<FakeWindowHandle> mBottomWindow;
7126};
7127
7128TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7129 PointF touchedPoint = {10, 10};
7130
7131 NotifyMotionArgs motionArgs =
7132 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7133 ADISPLAY_ID_DEFAULT, {touchedPoint});
7134 mDispatcher->notifyMotion(&motionArgs);
7135
7136 mNoInputWindow->assertNoEvents();
7137 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7138 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7139 // and therefore should prevent mBottomWindow from receiving touches
7140 mBottomWindow->assertNoEvents();
7141}
7142
7143/**
7144 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7145 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7146 */
7147TEST_F(InputDispatcherMultiWindowOcclusionTests,
7148 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007149 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7150 "Window with input channel and NO_INPUT_CHANNEL",
7151 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007152
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007153 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007154 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7155 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7156
7157 PointF touchedPoint = {10, 10};
7158
7159 NotifyMotionArgs motionArgs =
7160 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7161 ADISPLAY_ID_DEFAULT, {touchedPoint});
7162 mDispatcher->notifyMotion(&motionArgs);
7163
7164 mNoInputWindow->assertNoEvents();
7165 mBottomWindow->assertNoEvents();
7166}
7167
Vishnu Nair958da932020-08-21 17:12:37 -07007168class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7169protected:
7170 std::shared_ptr<FakeApplicationHandle> mApp;
7171 sp<FakeWindowHandle> mWindow;
7172 sp<FakeWindowHandle> mMirror;
7173
7174 virtual void SetUp() override {
7175 InputDispatcherTest::SetUp();
7176 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007177 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7178 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7179 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7181 mWindow->setFocusable(true);
7182 mMirror->setFocusable(true);
7183 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7184 }
7185};
7186
7187TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7188 // Request focus on a mirrored window
7189 setFocusedWindow(mMirror);
7190
7191 // window gets focused
7192 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7194 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007195 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7196}
7197
7198// A focused & mirrored window remains focused only if the window and its mirror are both
7199// focusable.
7200TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7201 setFocusedWindow(mMirror);
7202
7203 // window gets focused
7204 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7206 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007207 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7209 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007210 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7211
7212 mMirror->setFocusable(false);
7213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7214
7215 // window loses focus since one of the windows associated with the token in not focusable
7216 mWindow->consumeFocusEvent(false);
7217
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007218 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7219 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007220 mWindow->assertNoEvents();
7221}
7222
7223// A focused & mirrored window remains focused until the window and its mirror both become
7224// invisible.
7225TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7226 setFocusedWindow(mMirror);
7227
7228 // window gets focused
7229 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7231 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007232 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7234 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007235 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7236
7237 mMirror->setVisible(false);
7238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7239
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7241 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007242 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7244 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007245 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7246
7247 mWindow->setVisible(false);
7248 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7249
7250 // window loses focus only after all windows associated with the token become invisible.
7251 mWindow->consumeFocusEvent(false);
7252
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007253 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7254 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007255 mWindow->assertNoEvents();
7256}
7257
7258// A focused & mirrored window remains focused until both windows are removed.
7259TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7260 setFocusedWindow(mMirror);
7261
7262 // window gets focused
7263 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7265 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007266 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7268 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007269 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7270
7271 // single window is removed but the window token remains focused
7272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7273
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7275 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007276 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7278 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007279 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7280
7281 // Both windows are removed
7282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7283 mWindow->consumeFocusEvent(false);
7284
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007285 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7286 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007287 mWindow->assertNoEvents();
7288}
7289
7290// Focus request can be pending until one window becomes visible.
7291TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7292 // Request focus on an invisible mirror.
7293 mWindow->setVisible(false);
7294 mMirror->setVisible(false);
7295 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7296 setFocusedWindow(mMirror);
7297
7298 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007300 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7301 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007302
7303 mMirror->setVisible(true);
7304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7305
7306 // window gets focused
7307 mWindow->consumeFocusEvent(true);
7308 // window gets the pending key event
7309 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7310}
Prabir Pradhan99987712020-11-10 18:43:05 -08007311
7312class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7313protected:
7314 std::shared_ptr<FakeApplicationHandle> mApp;
7315 sp<FakeWindowHandle> mWindow;
7316 sp<FakeWindowHandle> mSecondWindow;
7317
7318 void SetUp() override {
7319 InputDispatcherTest::SetUp();
7320 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007321 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007322 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007323 mSecondWindow =
7324 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007325 mSecondWindow->setFocusable(true);
7326
7327 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7328 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7329
7330 setFocusedWindow(mWindow);
7331 mWindow->consumeFocusEvent(true);
7332 }
7333
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007334 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
7335 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007336 mDispatcher->notifyPointerCaptureChanged(&args);
7337 }
7338
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007339 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7340 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007341 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007342 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7343 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007344 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007345 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007346 }
7347};
7348
7349TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7350 // Ensure that capture cannot be obtained for unfocused windows.
7351 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7352 mFakePolicy->assertSetPointerCaptureNotCalled();
7353 mSecondWindow->assertNoEvents();
7354
7355 // Ensure that capture can be enabled from the focus window.
7356 requestAndVerifyPointerCapture(mWindow, true);
7357
7358 // Ensure that capture cannot be disabled from a window that does not have capture.
7359 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7360 mFakePolicy->assertSetPointerCaptureNotCalled();
7361
7362 // Ensure that capture can be disabled from the window with capture.
7363 requestAndVerifyPointerCapture(mWindow, false);
7364}
7365
7366TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007367 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007368
7369 setFocusedWindow(mSecondWindow);
7370
7371 // Ensure that the capture disabled event was sent first.
7372 mWindow->consumeCaptureEvent(false);
7373 mWindow->consumeFocusEvent(false);
7374 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007375 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007376
7377 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007378 notifyPointerCaptureChanged({});
7379 notifyPointerCaptureChanged(request);
7380 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007381 mWindow->assertNoEvents();
7382 mSecondWindow->assertNoEvents();
7383 mFakePolicy->assertSetPointerCaptureNotCalled();
7384}
7385
7386TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007387 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007388
7389 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007390 notifyPointerCaptureChanged({});
7391 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007392
7393 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007394 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007395 mWindow->consumeCaptureEvent(false);
7396 mWindow->assertNoEvents();
7397}
7398
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007399TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7400 requestAndVerifyPointerCapture(mWindow, true);
7401
7402 // The first window loses focus.
7403 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007404 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007405 mWindow->consumeCaptureEvent(false);
7406
7407 // Request Pointer Capture from the second window before the notification from InputReader
7408 // arrives.
7409 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007410 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007411
7412 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007413 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007414
7415 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007416 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007417
7418 mSecondWindow->consumeFocusEvent(true);
7419 mSecondWindow->consumeCaptureEvent(true);
7420}
7421
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007422TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7423 // App repeatedly enables and disables capture.
7424 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7425 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7426 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7427 mFakePolicy->assertSetPointerCaptureCalled(false);
7428 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7429 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7430
7431 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7432 // first request is now stale, this should do nothing.
7433 notifyPointerCaptureChanged(firstRequest);
7434 mWindow->assertNoEvents();
7435
7436 // InputReader notifies that the second request was enabled.
7437 notifyPointerCaptureChanged(secondRequest);
7438 mWindow->consumeCaptureEvent(true);
7439}
7440
Prabir Pradhan7092e262022-05-03 16:51:09 +00007441TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7442 requestAndVerifyPointerCapture(mWindow, true);
7443
7444 // App toggles pointer capture off and on.
7445 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7446 mFakePolicy->assertSetPointerCaptureCalled(false);
7447
7448 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7449 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7450
7451 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7452 // preceding "disable" request.
7453 notifyPointerCaptureChanged(enableRequest);
7454
7455 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7456 // any notifications.
7457 mWindow->assertNoEvents();
7458}
7459
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007460class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7461protected:
7462 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007463
7464 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7465 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7466
7467 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7468 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7469
7470 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7471 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7472 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7473 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7474 MAXIMUM_OBSCURING_OPACITY);
7475
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007476 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007477 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007478 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007479
7480 sp<FakeWindowHandle> mTouchWindow;
7481
7482 virtual void SetUp() override {
7483 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007484 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007485 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7486 }
7487
7488 virtual void TearDown() override {
7489 InputDispatcherTest::TearDown();
7490 mTouchWindow.clear();
7491 }
7492
chaviw3277faf2021-05-19 16:45:23 -05007493 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7494 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007495 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007496 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007497 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007498 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007499 return window;
7500 }
7501
7502 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7503 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7504 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007505 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007506 // Generate an arbitrary PID based on the UID
7507 window->setOwnerInfo(1777 + (uid % 10000), uid);
7508 return window;
7509 }
7510
7511 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
7512 NotifyMotionArgs args =
7513 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7514 ADISPLAY_ID_DEFAULT, points);
7515 mDispatcher->notifyMotion(&args);
7516 }
7517};
7518
7519TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007520 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007521 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007523
7524 touch();
7525
7526 mTouchWindow->assertNoEvents();
7527}
7528
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007529TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007530 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7531 const sp<FakeWindowHandle>& w =
7532 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7533 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7534
7535 touch();
7536
7537 mTouchWindow->assertNoEvents();
7538}
7539
7540TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007541 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7542 const sp<FakeWindowHandle>& w =
7543 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7544 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7545
7546 touch();
7547
7548 w->assertNoEvents();
7549}
7550
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007551TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007552 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007554
7555 touch();
7556
7557 mTouchWindow->consumeAnyMotionDown();
7558}
7559
7560TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007561 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007562 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007563 w->setFrame(Rect(0, 0, 50, 50));
7564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007565
7566 touch({PointF{100, 100}});
7567
7568 mTouchWindow->consumeAnyMotionDown();
7569}
7570
7571TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007572 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007573 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007574 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7575
7576 touch();
7577
7578 mTouchWindow->consumeAnyMotionDown();
7579}
7580
7581TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7582 const sp<FakeWindowHandle>& w =
7583 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007585
7586 touch();
7587
7588 mTouchWindow->consumeAnyMotionDown();
7589}
7590
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007591TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7592 const sp<FakeWindowHandle>& w =
7593 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7594 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7595
7596 touch();
7597
7598 w->assertNoEvents();
7599}
7600
7601/**
7602 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7603 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7604 * window, the occluding window will still receive ACTION_OUTSIDE event.
7605 */
7606TEST_F(InputDispatcherUntrustedTouchesTest,
7607 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7608 const sp<FakeWindowHandle>& w =
7609 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007610 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007611 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7612
7613 touch();
7614
7615 w->consumeMotionOutside();
7616}
7617
7618TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7619 const sp<FakeWindowHandle>& w =
7620 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007621 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7623
7624 touch();
7625
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007626 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007627}
7628
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007629TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007630 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007631 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7632 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007633 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7634
7635 touch();
7636
7637 mTouchWindow->consumeAnyMotionDown();
7638}
7639
7640TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7641 const sp<FakeWindowHandle>& w =
7642 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7643 MAXIMUM_OBSCURING_OPACITY);
7644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007645
7646 touch();
7647
7648 mTouchWindow->consumeAnyMotionDown();
7649}
7650
7651TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007652 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007653 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7654 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007655 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7656
7657 touch();
7658
7659 mTouchWindow->assertNoEvents();
7660}
7661
7662TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7663 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7664 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007665 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7666 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007667 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007668 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7669 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007670 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7671
7672 touch();
7673
7674 mTouchWindow->assertNoEvents();
7675}
7676
7677TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7678 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7679 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007680 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7681 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007682 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007683 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7684 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007685 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7686
7687 touch();
7688
7689 mTouchWindow->consumeAnyMotionDown();
7690}
7691
7692TEST_F(InputDispatcherUntrustedTouchesTest,
7693 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7694 const sp<FakeWindowHandle>& wB =
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 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007698 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7699 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7701
7702 touch();
7703
7704 mTouchWindow->consumeAnyMotionDown();
7705}
7706
7707TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7708 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007709 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7710 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007711 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007712 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7713 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007715
7716 touch();
7717
7718 mTouchWindow->assertNoEvents();
7719}
7720
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007721TEST_F(InputDispatcherUntrustedTouchesTest,
7722 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7723 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007724 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7725 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007726 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007727 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7728 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7730
7731 touch();
7732
7733 mTouchWindow->assertNoEvents();
7734}
7735
7736TEST_F(InputDispatcherUntrustedTouchesTest,
7737 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7738 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007739 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7740 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007741 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007742 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7743 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007744 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7745
7746 touch();
7747
7748 mTouchWindow->consumeAnyMotionDown();
7749}
7750
7751TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7752 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007753 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7754 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007755 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7756
7757 touch();
7758
7759 mTouchWindow->consumeAnyMotionDown();
7760}
7761
7762TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7763 const sp<FakeWindowHandle>& w =
7764 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7765 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7766
7767 touch();
7768
7769 mTouchWindow->consumeAnyMotionDown();
7770}
7771
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007772TEST_F(InputDispatcherUntrustedTouchesTest,
7773 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7774 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7775 const sp<FakeWindowHandle>& w =
7776 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7777 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7778
7779 touch();
7780
7781 mTouchWindow->assertNoEvents();
7782}
7783
7784TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7785 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7786 const sp<FakeWindowHandle>& w =
7787 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7788 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7789
7790 touch();
7791
7792 mTouchWindow->consumeAnyMotionDown();
7793}
7794
7795TEST_F(InputDispatcherUntrustedTouchesTest,
7796 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7797 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7798 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007799 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7800 OPACITY_ABOVE_THRESHOLD);
7801 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7802
7803 touch();
7804
7805 mTouchWindow->consumeAnyMotionDown();
7806}
7807
7808TEST_F(InputDispatcherUntrustedTouchesTest,
7809 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7810 const sp<FakeWindowHandle>& w1 =
7811 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7812 OPACITY_BELOW_THRESHOLD);
7813 const sp<FakeWindowHandle>& w2 =
7814 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7815 OPACITY_BELOW_THRESHOLD);
7816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7817
7818 touch();
7819
7820 mTouchWindow->assertNoEvents();
7821}
7822
7823/**
7824 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7825 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7826 * (which alone would result in allowing touches) does not affect the blocking behavior.
7827 */
7828TEST_F(InputDispatcherUntrustedTouchesTest,
7829 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7830 const sp<FakeWindowHandle>& wB =
7831 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7832 OPACITY_BELOW_THRESHOLD);
7833 const sp<FakeWindowHandle>& wC =
7834 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7835 OPACITY_BELOW_THRESHOLD);
7836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7837
7838 touch();
7839
7840 mTouchWindow->assertNoEvents();
7841}
7842
7843/**
7844 * This test is testing that a window from a different UID but with same application token doesn't
7845 * block the touch. Apps can share the application token for close UI collaboration for example.
7846 */
7847TEST_F(InputDispatcherUntrustedTouchesTest,
7848 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7849 const sp<FakeWindowHandle>& w =
7850 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7851 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007852 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7853
7854 touch();
7855
7856 mTouchWindow->consumeAnyMotionDown();
7857}
7858
arthurhungb89ccb02020-12-30 16:19:01 +08007859class InputDispatcherDragTests : public InputDispatcherTest {
7860protected:
7861 std::shared_ptr<FakeApplicationHandle> mApp;
7862 sp<FakeWindowHandle> mWindow;
7863 sp<FakeWindowHandle> mSecondWindow;
7864 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007865 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007866 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7867 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007868
7869 void SetUp() override {
7870 InputDispatcherTest::SetUp();
7871 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007872 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007873 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007874
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007875 mSecondWindow =
7876 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007877 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007878
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007879 mSpyWindow =
7880 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007881 mSpyWindow->setSpy(true);
7882 mSpyWindow->setTrustedOverlay(true);
7883 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7884
arthurhungb89ccb02020-12-30 16:19:01 +08007885 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007887 }
7888
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007889 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7890 switch (fromSource) {
7891 case AINPUT_SOURCE_TOUCHSCREEN:
7892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7893 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7894 ADISPLAY_ID_DEFAULT, {50, 50}))
7895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7896 break;
7897 case AINPUT_SOURCE_STYLUS:
7898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7899 injectMotionEvent(
7900 mDispatcher,
7901 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7902 AINPUT_SOURCE_STYLUS)
7903 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007904 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007905 .x(50)
7906 .y(50))
7907 .build()));
7908 break;
7909 case AINPUT_SOURCE_MOUSE:
7910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7911 injectMotionEvent(
7912 mDispatcher,
7913 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7914 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7915 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007916 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007917 .x(50)
7918 .y(50))
7919 .build()));
7920 break;
7921 default:
7922 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7923 }
arthurhungb89ccb02020-12-30 16:19:01 +08007924
7925 // Window should receive motion event.
7926 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007927 // Spy window should also receive motion event
7928 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007929 }
7930
7931 // Start performing drag, we will create a drag window and transfer touch to it.
7932 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7933 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007934 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007935 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007936 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00007937 }
arthurhungb89ccb02020-12-30 16:19:01 +08007938
7939 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007940 mDragWindow =
7941 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007942 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08007943 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007944 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007945
7946 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00007947 bool transferred =
7948 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00007949 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00007950 if (transferred) {
7951 mWindow->consumeMotionCancel();
7952 mDragWindow->consumeMotionDown();
7953 }
7954 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08007955 }
7956};
7957
7958TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007959 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08007960
7961 // Move on window.
7962 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7963 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7964 ADISPLAY_ID_DEFAULT, {50, 50}))
7965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7966 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7967 mWindow->consumeDragEvent(false, 50, 50);
7968 mSecondWindow->assertNoEvents();
7969
7970 // Move to another window.
7971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7972 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7973 ADISPLAY_ID_DEFAULT, {150, 50}))
7974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7975 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7976 mWindow->consumeDragEvent(true, 150, 50);
7977 mSecondWindow->consumeDragEvent(false, 50, 50);
7978
7979 // Move back to original window.
7980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7981 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7982 ADISPLAY_ID_DEFAULT, {50, 50}))
7983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7984 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7985 mWindow->consumeDragEvent(false, 50, 50);
7986 mSecondWindow->consumeDragEvent(true, -50, 50);
7987
7988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7989 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
7990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7991 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7992 mWindow->assertNoEvents();
7993 mSecondWindow->assertNoEvents();
7994}
7995
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007996TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007997 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007998
7999 // No cancel event after drag start
8000 mSpyWindow->assertNoEvents();
8001
8002 const MotionEvent secondFingerDownEvent =
8003 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8004 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008005 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8006 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008007 .build();
8008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8009 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8010 InputEventInjectionSync::WAIT_FOR_RESULT))
8011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8012
8013 // Receives cancel for first pointer after next pointer down
8014 mSpyWindow->consumeMotionCancel();
8015 mSpyWindow->consumeMotionDown();
8016
8017 mSpyWindow->assertNoEvents();
8018}
8019
arthurhungf452d0b2021-01-06 00:19:52 +08008020TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008021 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008022
8023 // Move on window.
8024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8025 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8026 ADISPLAY_ID_DEFAULT, {50, 50}))
8027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8028 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8029 mWindow->consumeDragEvent(false, 50, 50);
8030 mSecondWindow->assertNoEvents();
8031
8032 // Move to another window.
8033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8034 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8035 ADISPLAY_ID_DEFAULT, {150, 50}))
8036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8037 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8038 mWindow->consumeDragEvent(true, 150, 50);
8039 mSecondWindow->consumeDragEvent(false, 50, 50);
8040
8041 // drop to another window.
8042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8043 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8044 {150, 50}))
8045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8046 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8047 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8048 mWindow->assertNoEvents();
8049 mSecondWindow->assertNoEvents();
8050}
8051
arthurhung6d4bed92021-03-17 11:59:33 +08008052TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008053 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008054
8055 // Move on window and keep button pressed.
8056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8057 injectMotionEvent(mDispatcher,
8058 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8059 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008060 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008061 .build()))
8062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8063 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8064 mWindow->consumeDragEvent(false, 50, 50);
8065 mSecondWindow->assertNoEvents();
8066
8067 // Move to another window and release button, expect to drop item.
8068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8069 injectMotionEvent(mDispatcher,
8070 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8071 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008072 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008073 .build()))
8074 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8075 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8076 mWindow->assertNoEvents();
8077 mSecondWindow->assertNoEvents();
8078 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8079
8080 // nothing to the window.
8081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8082 injectMotionEvent(mDispatcher,
8083 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8084 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008085 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008086 .build()))
8087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8088 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8089 mWindow->assertNoEvents();
8090 mSecondWindow->assertNoEvents();
8091}
8092
Arthur Hung54745652022-04-20 07:17:41 +00008093TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008094 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008095
8096 // Set second window invisible.
8097 mSecondWindow->setVisible(false);
8098 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8099
8100 // Move on window.
8101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8102 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8103 ADISPLAY_ID_DEFAULT, {50, 50}))
8104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8105 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8106 mWindow->consumeDragEvent(false, 50, 50);
8107 mSecondWindow->assertNoEvents();
8108
8109 // Move to another window.
8110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8111 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8112 ADISPLAY_ID_DEFAULT, {150, 50}))
8113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8114 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8115 mWindow->consumeDragEvent(true, 150, 50);
8116 mSecondWindow->assertNoEvents();
8117
8118 // drop to another window.
8119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8120 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8121 {150, 50}))
8122 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8123 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8124 mFakePolicy->assertDropTargetEquals(nullptr);
8125 mWindow->assertNoEvents();
8126 mSecondWindow->assertNoEvents();
8127}
8128
Arthur Hung54745652022-04-20 07:17:41 +00008129TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008130 // Ensure window could track pointerIds if it didn't support split touch.
8131 mWindow->setPreventSplitting(true);
8132
Arthur Hung54745652022-04-20 07:17:41 +00008133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8134 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8135 {50, 50}))
8136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8137 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8138
8139 const MotionEvent secondFingerDownEvent =
8140 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8141 .displayId(ADISPLAY_ID_DEFAULT)
8142 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008143 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8144 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008145 .build();
8146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8147 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8148 InputEventInjectionSync::WAIT_FOR_RESULT))
8149 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008150 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008151
8152 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008153 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008154}
8155
8156TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8157 // First down on second window.
8158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8159 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8160 {150, 50}))
8161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8162
8163 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8164
8165 // Second down on first window.
8166 const MotionEvent secondFingerDownEvent =
8167 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8168 .displayId(ADISPLAY_ID_DEFAULT)
8169 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008170 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8171 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008172 .build();
8173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8174 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8175 InputEventInjectionSync::WAIT_FOR_RESULT))
8176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8177 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8178
8179 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008180 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008181
8182 // Move on window.
8183 const MotionEvent secondFingerMoveEvent =
8184 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8185 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008186 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8187 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008188 .build();
8189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8190 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8191 InputEventInjectionSync::WAIT_FOR_RESULT));
8192 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8193 mWindow->consumeDragEvent(false, 50, 50);
8194 mSecondWindow->consumeMotionMove();
8195
8196 // Release the drag pointer should perform drop.
8197 const MotionEvent secondFingerUpEvent =
8198 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8199 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008200 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8201 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008202 .build();
8203 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8204 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8205 InputEventInjectionSync::WAIT_FOR_RESULT));
8206 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8207 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8208 mWindow->assertNoEvents();
8209 mSecondWindow->consumeMotionMove();
8210}
8211
Arthur Hung3915c1f2022-05-31 07:17:17 +00008212TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008213 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008214
8215 // Update window of second display.
8216 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008217 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008218 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8219
8220 // Let second display has a touch state.
8221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8222 injectMotionEvent(mDispatcher,
8223 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8224 AINPUT_SOURCE_TOUCHSCREEN)
8225 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008226 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008227 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008228 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008229 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008230 // Update window again.
8231 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8232
8233 // Move on window.
8234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8235 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8236 ADISPLAY_ID_DEFAULT, {50, 50}))
8237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8238 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8239 mWindow->consumeDragEvent(false, 50, 50);
8240 mSecondWindow->assertNoEvents();
8241
8242 // Move to another window.
8243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8244 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8245 ADISPLAY_ID_DEFAULT, {150, 50}))
8246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8247 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8248 mWindow->consumeDragEvent(true, 150, 50);
8249 mSecondWindow->consumeDragEvent(false, 50, 50);
8250
8251 // drop to another window.
8252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8253 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8254 {150, 50}))
8255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8256 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8257 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8258 mWindow->assertNoEvents();
8259 mSecondWindow->assertNoEvents();
8260}
8261
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008262TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8263 startDrag(true, AINPUT_SOURCE_MOUSE);
8264 // Move on window.
8265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8266 injectMotionEvent(mDispatcher,
8267 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8268 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8269 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008270 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008271 .x(50)
8272 .y(50))
8273 .build()))
8274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8275 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8276 mWindow->consumeDragEvent(false, 50, 50);
8277 mSecondWindow->assertNoEvents();
8278
8279 // Move to another window.
8280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8281 injectMotionEvent(mDispatcher,
8282 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8283 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8284 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008285 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008286 .x(150)
8287 .y(50))
8288 .build()))
8289 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8290 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8291 mWindow->consumeDragEvent(true, 150, 50);
8292 mSecondWindow->consumeDragEvent(false, 50, 50);
8293
8294 // drop to another window.
8295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8296 injectMotionEvent(mDispatcher,
8297 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8298 .buttonState(0)
8299 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008300 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008301 .x(150)
8302 .y(50))
8303 .build()))
8304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8305 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8306 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8307 mWindow->assertNoEvents();
8308 mSecondWindow->assertNoEvents();
8309}
8310
Vishnu Nair062a8672021-09-03 16:07:44 -07008311class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8312
8313TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008315 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8316 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008317 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008318 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8319 window->setFocusable(true);
8320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8321 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008322 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008323
8324 // With the flag set, window should not get any input
8325 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8326 mDispatcher->notifyKey(&keyArgs);
8327 window->assertNoEvents();
8328
8329 NotifyMotionArgs motionArgs =
8330 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8331 ADISPLAY_ID_DEFAULT);
8332 mDispatcher->notifyMotion(&motionArgs);
8333 window->assertNoEvents();
8334
8335 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008336 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008337 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8338
8339 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8340 mDispatcher->notifyKey(&keyArgs);
8341 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8342
8343 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8344 ADISPLAY_ID_DEFAULT);
8345 mDispatcher->notifyMotion(&motionArgs);
8346 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8347 window->assertNoEvents();
8348}
8349
8350TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8351 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8352 std::make_shared<FakeApplicationHandle>();
8353 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008354 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8355 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008356 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8357 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008358 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008360 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8361 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008362 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008363 window->setOwnerInfo(222, 222);
8364 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8365 window->setFocusable(true);
8366 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8367 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008368 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008369
8370 // With the flag set, window should not get any input
8371 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8372 mDispatcher->notifyKey(&keyArgs);
8373 window->assertNoEvents();
8374
8375 NotifyMotionArgs motionArgs =
8376 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8377 ADISPLAY_ID_DEFAULT);
8378 mDispatcher->notifyMotion(&motionArgs);
8379 window->assertNoEvents();
8380
8381 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008382 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8384
8385 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8386 mDispatcher->notifyKey(&keyArgs);
8387 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8388
8389 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8390 ADISPLAY_ID_DEFAULT);
8391 mDispatcher->notifyMotion(&motionArgs);
8392 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8393 window->assertNoEvents();
8394}
8395
8396TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8397 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8398 std::make_shared<FakeApplicationHandle>();
8399 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008400 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8401 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008402 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8403 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008404 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008406 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8407 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008408 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008409 window->setOwnerInfo(222, 222);
8410 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8411 window->setFocusable(true);
8412 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8413 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008414 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008415
8416 // With the flag set, window should not get any input
8417 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8418 mDispatcher->notifyKey(&keyArgs);
8419 window->assertNoEvents();
8420
8421 NotifyMotionArgs motionArgs =
8422 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8423 ADISPLAY_ID_DEFAULT);
8424 mDispatcher->notifyMotion(&motionArgs);
8425 window->assertNoEvents();
8426
8427 // When the window is no longer obscured because it went on top, it should get input
8428 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8429
8430 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8431 mDispatcher->notifyKey(&keyArgs);
8432 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8433
8434 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8435 ADISPLAY_ID_DEFAULT);
8436 mDispatcher->notifyMotion(&motionArgs);
8437 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8438 window->assertNoEvents();
8439}
8440
Antonio Kantekf16f2832021-09-28 04:39:20 +00008441class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8442protected:
8443 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008444 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008445 sp<FakeWindowHandle> mWindow;
8446 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008447 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008448
8449 void SetUp() override {
8450 InputDispatcherTest::SetUp();
8451
8452 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008453 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008454 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008455 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008456 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008457 mSecondWindow =
8458 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008459 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008460 mThirdWindow =
8461 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8462 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8463 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008464
8465 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8467 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8468 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008469 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008470
Antonio Kantek15beb512022-06-13 22:35:41 +00008471 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008472 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008473 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008474 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8475 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008476 mThirdWindow->assertNoEvents();
8477 }
8478
8479 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8480 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008481 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008482 SECOND_DISPLAY_ID)) {
8483 mWindow->assertNoEvents();
8484 mSecondWindow->assertNoEvents();
8485 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008486 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008487 }
8488
Antonio Kantek15beb512022-06-13 22:35:41 +00008489 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8490 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008491 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8492 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008493 mWindow->consumeTouchModeEvent(inTouchMode);
8494 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008495 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008496 }
8497};
8498
Antonio Kantek26defcf2022-02-08 01:12:27 +00008499TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008500 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008501 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8502 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008503 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008504}
8505
Antonio Kantek26defcf2022-02-08 01:12:27 +00008506TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8507 const WindowInfo& windowInfo = *mWindow->getInfo();
8508 int32_t ownerPid = windowInfo.ownerPid;
8509 int32_t ownerUid = windowInfo.ownerUid;
8510 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8511 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008512 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008513 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008514 mWindow->assertNoEvents();
8515 mSecondWindow->assertNoEvents();
8516}
8517
8518TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8519 const WindowInfo& windowInfo = *mWindow->getInfo();
8520 int32_t ownerPid = windowInfo.ownerPid;
8521 int32_t ownerUid = windowInfo.ownerUid;
8522 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008523 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008524 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008525}
8526
Antonio Kantekf16f2832021-09-28 04:39:20 +00008527TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008528 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008529 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8530 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008531 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008532 mWindow->assertNoEvents();
8533 mSecondWindow->assertNoEvents();
8534}
8535
Antonio Kantek15beb512022-06-13 22:35:41 +00008536TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8537 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8538 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8539 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008540 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008541 mWindow->assertNoEvents();
8542 mSecondWindow->assertNoEvents();
8543 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8544}
8545
Antonio Kantek48710e42022-03-24 14:19:30 -07008546TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8547 // Interact with the window first.
8548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8549 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8550 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8551
8552 // Then remove focus.
8553 mWindow->setFocusable(false);
8554 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8555
8556 // Assert that caller can switch touch mode by owning one of the last interacted window.
8557 const WindowInfo& windowInfo = *mWindow->getInfo();
8558 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8559 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008560 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008561}
8562
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008563class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8564public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008565 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008566 std::shared_ptr<FakeApplicationHandle> application =
8567 std::make_shared<FakeApplicationHandle>();
8568 std::string name = "Fake Spy ";
8569 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008570 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8571 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008572 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008573 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008574 return spy;
8575 }
8576
8577 sp<FakeWindowHandle> createForeground() {
8578 std::shared_ptr<FakeApplicationHandle> application =
8579 std::make_shared<FakeApplicationHandle>();
8580 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008581 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8582 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008583 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008584 return window;
8585 }
8586
8587private:
8588 int mSpyCount{0};
8589};
8590
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008591using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008592/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008593 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8594 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008595TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8596 ScopedSilentDeath _silentDeath;
8597
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008598 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008599 spy->setTrustedOverlay(false);
8600 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8601 ".* not a trusted overlay");
8602}
8603
8604/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008605 * Input injection into a display with a spy window but no foreground windows should succeed.
8606 */
8607TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008608 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8610
8611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8612 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8614 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8615}
8616
8617/**
8618 * Verify the order in which different input windows receive events. The touched foreground window
8619 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8620 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8621 * receive events before ones belows it.
8622 *
8623 * Here, we set up a scenario with four windows in the following Z order from the top:
8624 * spy1, spy2, window, spy3.
8625 * We then inject an event and verify that the foreground "window" receives it first, followed by
8626 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8627 * window.
8628 */
8629TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8630 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008631 auto spy1 = createSpy();
8632 auto spy2 = createSpy();
8633 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8635 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8636 const size_t numChannels = channels.size();
8637
Michael Wright8e9a8562022-02-09 13:44:29 +00008638 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008639 if (!epollFd.ok()) {
8640 FAIL() << "Failed to create epoll fd";
8641 }
8642
8643 for (size_t i = 0; i < numChannels; i++) {
8644 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8645 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8646 FAIL() << "Failed to add fd to epoll";
8647 }
8648 }
8649
8650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8651 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8652 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8653
8654 std::vector<size_t> eventOrder;
8655 std::vector<struct epoll_event> events(numChannels);
8656 for (;;) {
8657 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8658 (100ms).count());
8659 if (nFds < 0) {
8660 FAIL() << "Failed to call epoll_wait";
8661 }
8662 if (nFds == 0) {
8663 break; // epoll_wait timed out
8664 }
8665 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008666 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008667 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008668 channels[i]->consumeMotionDown();
8669 }
8670 }
8671
8672 // Verify the order in which the events were received.
8673 EXPECT_EQ(3u, eventOrder.size());
8674 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8675 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8676 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8677}
8678
8679/**
8680 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8681 */
8682TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8683 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008684 auto spy = createSpy();
8685 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8687
8688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8689 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8692 spy->assertNoEvents();
8693}
8694
8695/**
8696 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8697 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8698 * to the window.
8699 */
8700TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8701 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008702 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008703 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8705
8706 // Inject an event outside the spy window's touchable region.
8707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8708 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8710 window->consumeMotionDown();
8711 spy->assertNoEvents();
8712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8713 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8714 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8715 window->consumeMotionUp();
8716 spy->assertNoEvents();
8717
8718 // Inject an event inside the spy window's touchable region.
8719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8720 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8721 {5, 10}))
8722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8723 window->consumeMotionDown();
8724 spy->consumeMotionDown();
8725}
8726
8727/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008728 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008729 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008730 */
8731TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8732 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008733 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008734 auto spy = createSpy();
8735 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008736 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008737 spy->setFrame(Rect{0, 0, 20, 20});
8738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8739
8740 // Inject an event outside the spy window's frame and touchable region.
8741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008742 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8743 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8745 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008746 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008747}
8748
8749/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008750 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8751 * pointers that are down within its bounds.
8752 */
8753TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8754 auto windowLeft = createForeground();
8755 windowLeft->setFrame({0, 0, 100, 200});
8756 auto windowRight = createForeground();
8757 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008758 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008759 spy->setFrame({0, 0, 200, 200});
8760 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8761
8762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8763 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8764 {50, 50}))
8765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8766 windowLeft->consumeMotionDown();
8767 spy->consumeMotionDown();
8768
8769 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008770 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008771 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008772 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8773 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008774 .build();
8775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8776 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8777 InputEventInjectionSync::WAIT_FOR_RESULT))
8778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8779 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008780 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008781}
8782
8783/**
8784 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8785 * the spy should receive the second pointer with ACTION_DOWN.
8786 */
8787TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8788 auto window = createForeground();
8789 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008790 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008791 spyRight->setFrame({100, 0, 200, 200});
8792 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8793
8794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8795 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8796 {50, 50}))
8797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8798 window->consumeMotionDown();
8799 spyRight->assertNoEvents();
8800
8801 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008802 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008803 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008804 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8805 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008806 .build();
8807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8808 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8809 InputEventInjectionSync::WAIT_FOR_RESULT))
8810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008811 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008812 spyRight->consumeMotionDown();
8813}
8814
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008815/**
8816 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8817 * windows should be allowed to control split touch.
8818 */
8819TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008820 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008821 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008822 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008823 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008824
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008825 auto window = createForeground();
8826 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008827
8828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8829
8830 // First finger down, no window touched.
8831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8832 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8833 {100, 200}))
8834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8835 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8836 window->assertNoEvents();
8837
8838 // Second finger down on window, the window should receive touch down.
8839 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008840 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008841 .displayId(ADISPLAY_ID_DEFAULT)
8842 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008843 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8844 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008845 .build();
8846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8847 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8848 InputEventInjectionSync::WAIT_FOR_RESULT))
8849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8850
8851 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008852 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008853}
8854
8855/**
8856 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8857 * do not receive key events.
8858 */
8859TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008860 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008861 spy->setFocusable(false);
8862
8863 auto window = createForeground();
8864 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8865 setFocusedWindow(window);
8866 window->consumeFocusEvent(true);
8867
8868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8869 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8870 window->consumeKeyDown(ADISPLAY_ID_NONE);
8871
8872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8873 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8874 window->consumeKeyUp(ADISPLAY_ID_NONE);
8875
8876 spy->assertNoEvents();
8877}
8878
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008879using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8880
8881/**
8882 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8883 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8884 */
8885TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8886 auto window = createForeground();
8887 auto spy1 = createSpy();
8888 auto spy2 = createSpy();
8889 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8890
8891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8892 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8894 window->consumeMotionDown();
8895 spy1->consumeMotionDown();
8896 spy2->consumeMotionDown();
8897
8898 // Pilfer pointers from the second spy window.
8899 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8900 spy2->assertNoEvents();
8901 spy1->consumeMotionCancel();
8902 window->consumeMotionCancel();
8903
8904 // The rest of the gesture should only be sent to the second spy window.
8905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8906 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8907 ADISPLAY_ID_DEFAULT))
8908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8909 spy2->consumeMotionMove();
8910 spy1->assertNoEvents();
8911 window->assertNoEvents();
8912}
8913
8914/**
8915 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8916 * in the middle of the gesture.
8917 */
8918TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8919 auto window = createForeground();
8920 auto spy = createSpy();
8921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8922
8923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8924 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8926 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8927 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8928
8929 window->releaseChannel();
8930
8931 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8932
8933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8934 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8936 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8937}
8938
8939/**
8940 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8941 * the spy, but not to any other windows.
8942 */
8943TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8944 auto spy = createSpy();
8945 auto window = createForeground();
8946
8947 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8948
8949 // First finger down on the window and the spy.
8950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8951 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8952 {100, 200}))
8953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8954 spy->consumeMotionDown();
8955 window->consumeMotionDown();
8956
8957 // Spy window pilfers the pointers.
8958 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8959 window->consumeMotionCancel();
8960
8961 // Second finger down on the window and spy, but the window should not receive the pointer down.
8962 const MotionEvent secondFingerDownEvent =
8963 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8964 .displayId(ADISPLAY_ID_DEFAULT)
8965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008966 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8967 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008968 .build();
8969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8970 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8971 InputEventInjectionSync::WAIT_FOR_RESULT))
8972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8973
Harry Cutts33476232023-01-30 19:57:29 +00008974 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008975
8976 // Third finger goes down outside all windows, so injection should fail.
8977 const MotionEvent thirdFingerDownEvent =
8978 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8979 .displayId(ADISPLAY_ID_DEFAULT)
8980 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008981 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8982 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
8983 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008984 .build();
8985 ASSERT_EQ(InputEventInjectionResult::FAILED,
8986 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8987 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008988 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008989
8990 spy->assertNoEvents();
8991 window->assertNoEvents();
8992}
8993
8994/**
8995 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
8996 */
8997TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
8998 auto spy = createSpy();
8999 spy->setFrame(Rect(0, 0, 100, 100));
9000 auto window = createForeground();
9001 window->setFrame(Rect(0, 0, 200, 200));
9002
9003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9004
9005 // First finger down on the window only
9006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9007 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9008 {150, 150}))
9009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9010 window->consumeMotionDown();
9011
9012 // Second finger down on the spy and window
9013 const MotionEvent secondFingerDownEvent =
9014 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9015 .displayId(ADISPLAY_ID_DEFAULT)
9016 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009017 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9018 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009019 .build();
9020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9021 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9022 InputEventInjectionSync::WAIT_FOR_RESULT))
9023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9024 spy->consumeMotionDown();
9025 window->consumeMotionPointerDown(1);
9026
9027 // Third finger down on the spy and window
9028 const MotionEvent thirdFingerDownEvent =
9029 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9030 .displayId(ADISPLAY_ID_DEFAULT)
9031 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009032 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9033 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9034 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009035 .build();
9036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9037 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9038 InputEventInjectionSync::WAIT_FOR_RESULT))
9039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9040 spy->consumeMotionPointerDown(1);
9041 window->consumeMotionPointerDown(2);
9042
9043 // Spy window pilfers the pointers.
9044 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9045 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9046 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9047
9048 spy->assertNoEvents();
9049 window->assertNoEvents();
9050}
9051
9052/**
9053 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9054 * other windows should be canceled. If this results in the cancellation of all pointers for some
9055 * window, then that window should receive ACTION_CANCEL.
9056 */
9057TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9058 auto spy = createSpy();
9059 spy->setFrame(Rect(0, 0, 100, 100));
9060 auto window = createForeground();
9061 window->setFrame(Rect(0, 0, 200, 200));
9062
9063 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9064
9065 // First finger down on both spy and window
9066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9067 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9068 {10, 10}))
9069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9070 window->consumeMotionDown();
9071 spy->consumeMotionDown();
9072
9073 // Second finger down on the spy and window
9074 const MotionEvent secondFingerDownEvent =
9075 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9076 .displayId(ADISPLAY_ID_DEFAULT)
9077 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009078 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9079 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009080 .build();
9081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9082 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9083 InputEventInjectionSync::WAIT_FOR_RESULT))
9084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9085 spy->consumeMotionPointerDown(1);
9086 window->consumeMotionPointerDown(1);
9087
9088 // Spy window pilfers the pointers.
9089 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9090 window->consumeMotionCancel();
9091
9092 spy->assertNoEvents();
9093 window->assertNoEvents();
9094}
9095
9096/**
9097 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9098 * be sent to other windows
9099 */
9100TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9101 auto spy = createSpy();
9102 spy->setFrame(Rect(0, 0, 100, 100));
9103 auto window = createForeground();
9104 window->setFrame(Rect(0, 0, 200, 200));
9105
9106 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9107
9108 // First finger down on both window and spy
9109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9111 {10, 10}))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 window->consumeMotionDown();
9114 spy->consumeMotionDown();
9115
9116 // Spy window pilfers the pointers.
9117 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9118 window->consumeMotionCancel();
9119
9120 // Second finger down on the window only
9121 const MotionEvent secondFingerDownEvent =
9122 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9123 .displayId(ADISPLAY_ID_DEFAULT)
9124 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009125 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9126 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009127 .build();
9128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9129 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9130 InputEventInjectionSync::WAIT_FOR_RESULT))
9131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9132 window->consumeMotionDown();
9133 window->assertNoEvents();
9134
9135 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9136 spy->consumeMotionMove();
9137 spy->assertNoEvents();
9138}
9139
Prabir Pradhand65552b2021-10-07 11:23:50 -07009140class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9141public:
9142 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9143 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9144 std::make_shared<FakeApplicationHandle>();
9145 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009146 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9147 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009148 overlay->setFocusable(false);
9149 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009150 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009151 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009152 overlay->setTrustedOverlay(true);
9153
9154 std::shared_ptr<FakeApplicationHandle> application =
9155 std::make_shared<FakeApplicationHandle>();
9156 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009157 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9158 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009159 window->setFocusable(true);
9160 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009161
9162 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9164 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009165 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009166 return {std::move(overlay), std::move(window)};
9167 }
9168
9169 void sendFingerEvent(int32_t action) {
9170 NotifyMotionArgs motionArgs =
9171 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9172 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
9173 mDispatcher->notifyMotion(&motionArgs);
9174 }
9175
9176 void sendStylusEvent(int32_t action) {
9177 NotifyMotionArgs motionArgs =
9178 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9179 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009180 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhand65552b2021-10-07 11:23:50 -07009181 mDispatcher->notifyMotion(&motionArgs);
9182 }
9183};
9184
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009185using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9186
9187TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9188 ScopedSilentDeath _silentDeath;
9189
Prabir Pradhand65552b2021-10-07 11:23:50 -07009190 auto [overlay, window] = setupStylusOverlayScenario();
9191 overlay->setTrustedOverlay(false);
9192 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9193 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9194 ".* not a trusted overlay");
9195}
9196
9197TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9198 auto [overlay, window] = setupStylusOverlayScenario();
9199 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9200
9201 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9202 overlay->consumeMotionDown();
9203 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9204 overlay->consumeMotionUp();
9205
9206 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9207 window->consumeMotionDown();
9208 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9209 window->consumeMotionUp();
9210
9211 overlay->assertNoEvents();
9212 window->assertNoEvents();
9213}
9214
9215TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9216 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009217 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9219
9220 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9221 overlay->consumeMotionDown();
9222 window->consumeMotionDown();
9223 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9224 overlay->consumeMotionUp();
9225 window->consumeMotionUp();
9226
9227 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9228 window->consumeMotionDown();
9229 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9230 window->consumeMotionUp();
9231
9232 overlay->assertNoEvents();
9233 window->assertNoEvents();
9234}
9235
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009236/**
9237 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9238 * The scenario is as follows:
9239 * - The stylus interceptor overlay is configured as a spy window.
9240 * - The stylus interceptor spy receives the start of a new stylus gesture.
9241 * - It pilfers pointers and then configures itself to no longer be a spy.
9242 * - The stylus interceptor continues to receive the rest of the gesture.
9243 */
9244TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9245 auto [overlay, window] = setupStylusOverlayScenario();
9246 overlay->setSpy(true);
9247 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9248
9249 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9250 overlay->consumeMotionDown();
9251 window->consumeMotionDown();
9252
9253 // The interceptor pilfers the pointers.
9254 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9255 window->consumeMotionCancel();
9256
9257 // The interceptor configures itself so that it is no longer a spy.
9258 overlay->setSpy(false);
9259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9260
9261 // It continues to receive the rest of the stylus gesture.
9262 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9263 overlay->consumeMotionMove();
9264 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9265 overlay->consumeMotionUp();
9266
9267 window->assertNoEvents();
9268}
9269
Prabir Pradhan5735a322022-04-11 17:23:34 +00009270struct User {
9271 int32_t mPid;
9272 int32_t mUid;
9273 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9274 std::unique_ptr<InputDispatcher>& mDispatcher;
9275
9276 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9277 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9278
9279 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9280 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9281 ADISPLAY_ID_DEFAULT, {100, 200},
9282 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9283 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9284 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9285 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9286 }
9287
9288 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009289 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009290 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009291 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009292 mPolicyFlags);
9293 }
9294
9295 sp<FakeWindowHandle> createWindow() const {
9296 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9297 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009298 sp<FakeWindowHandle> window =
9299 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9300 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009301 window->setOwnerInfo(mPid, mUid);
9302 return window;
9303 }
9304};
9305
9306using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9307
9308TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9309 auto owner = User(mDispatcher, 10, 11);
9310 auto window = owner.createWindow();
9311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9312
9313 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9314 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9315 window->consumeMotionDown();
9316
9317 setFocusedWindow(window);
9318 window->consumeFocusEvent(true);
9319
9320 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9321 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9322 window->consumeKeyDown(ADISPLAY_ID_NONE);
9323}
9324
9325TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9326 auto owner = User(mDispatcher, 10, 11);
9327 auto window = owner.createWindow();
9328 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9329
9330 auto rando = User(mDispatcher, 20, 21);
9331 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9332 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9333
9334 setFocusedWindow(window);
9335 window->consumeFocusEvent(true);
9336
9337 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9338 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9339 window->assertNoEvents();
9340}
9341
9342TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9343 auto owner = User(mDispatcher, 10, 11);
9344 auto window = owner.createWindow();
9345 auto spy = owner.createWindow();
9346 spy->setSpy(true);
9347 spy->setTrustedOverlay(true);
9348 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9349
9350 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9351 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9352 spy->consumeMotionDown();
9353 window->consumeMotionDown();
9354}
9355
9356TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9357 auto owner = User(mDispatcher, 10, 11);
9358 auto window = owner.createWindow();
9359
9360 auto rando = User(mDispatcher, 20, 21);
9361 auto randosSpy = rando.createWindow();
9362 randosSpy->setSpy(true);
9363 randosSpy->setTrustedOverlay(true);
9364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9365
9366 // The event is targeted at owner's window, so injection should succeed, but the spy should
9367 // not receive the event.
9368 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9369 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9370 randosSpy->assertNoEvents();
9371 window->consumeMotionDown();
9372}
9373
9374TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9375 auto owner = User(mDispatcher, 10, 11);
9376 auto window = owner.createWindow();
9377
9378 auto rando = User(mDispatcher, 20, 21);
9379 auto randosSpy = rando.createWindow();
9380 randosSpy->setSpy(true);
9381 randosSpy->setTrustedOverlay(true);
9382 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9383
9384 // A user that has injection permission can inject into any window.
9385 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9386 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9387 ADISPLAY_ID_DEFAULT));
9388 randosSpy->consumeMotionDown();
9389 window->consumeMotionDown();
9390
9391 setFocusedWindow(randosSpy);
9392 randosSpy->consumeFocusEvent(true);
9393
9394 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9395 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9396 window->assertNoEvents();
9397}
9398
9399TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9400 auto owner = User(mDispatcher, 10, 11);
9401 auto window = owner.createWindow();
9402
9403 auto rando = User(mDispatcher, 20, 21);
9404 auto randosWindow = rando.createWindow();
9405 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9406 randosWindow->setWatchOutsideTouch(true);
9407 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9408
9409 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9410 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9411 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9412 window->consumeMotionDown();
9413 randosWindow->consumeMotionOutside();
9414}
9415
Garfield Tane84e6f92019-08-29 17:28:41 -07009416} // namespace android::inputdispatcher