blob: df1787b8e3e70b26587e94eebfb9db406668fd68 [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
chaviwd1c23182019-12-20 18:44:56 -0800108struct PointF {
109 float x;
110 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800111 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800112};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800113
Gang Wang342c9272020-01-13 13:15:04 -0500114/**
115 * Return a DOWN key event with KEYCODE_A.
116 */
117static KeyEvent getTestKeyEvent() {
118 KeyEvent event;
119
Garfield Tanfbe732e2020-01-24 11:26:14 -0800120 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
121 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
122 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500123 return event;
124}
125
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000126static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
127 ASSERT_EQ(expectedAction, receivedAction)
128 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
129 << MotionEvent::actionToString(receivedAction);
130}
131
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800132MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
133 bool matches = action == arg.getAction();
134 if (!matches) {
135 *result_listener << "expected action " << MotionEvent::actionToString(action)
136 << ", but got " << MotionEvent::actionToString(arg.getAction());
137 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800138 if (action == AMOTION_EVENT_ACTION_DOWN) {
139 if (!matches) {
140 *result_listener << "; ";
141 }
142 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
143 matches &= arg.getDownTime() == arg.getEventTime();
144 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800145 if (action == AMOTION_EVENT_ACTION_CANCEL) {
146 if (!matches) {
147 *result_listener << "; ";
148 }
149 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
150 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
151 }
152 return matches;
153}
154
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800155MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
156 return arg.getDownTime() == downTime;
157}
158
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800159MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
160 return arg.getDisplayId() == displayId;
161}
162
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800163MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
164 return arg.getDeviceId() == deviceId;
165}
166
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800167MATCHER_P(WithSource, source, "InputEvent with specified source") {
168 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
169 << inputEventSourceToString(arg.getSource());
170 return arg.getSource() == source;
171}
172
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800173MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
174 return arg.getFlags() == flags;
175}
176
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800177MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
178 if (arg.getPointerCount() != 1) {
179 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
180 return false;
181 }
Harry Cutts33476232023-01-30 19:57:29 +0000182 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800183}
184
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800185MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
186 return arg.getPointerCount() == pointerCount;
187}
188
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800189MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
190 // Build a map for the received pointers, by pointer id
191 std::map<int32_t /*pointerId*/, PointF> actualPointers;
192 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
193 const int32_t pointerId = arg.getPointerId(pointerIndex);
194 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
195 }
196 return pointers == actualPointers;
197}
198
Michael Wrightd02c5b62014-02-10 15:10:22 -0800199// --- FakeInputDispatcherPolicy ---
200
201class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
202 InputDispatcherConfiguration mConfig;
203
Prabir Pradhanedd96402022-02-15 01:46:16 -0800204 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
205
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000207 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208
209public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000210 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800211
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800212 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700213 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
214 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_KEY);
215 EXPECT_EQ(event.getDisplayId(), args.displayId);
216
217 const auto& keyEvent = static_cast<const KeyEvent&>(event);
218 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
219 EXPECT_EQ(keyEvent.getAction(), args.action);
220 });
Jackal Guof9696682018-10-05 12:23:23 +0800221 }
222
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700223 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
224 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
225 ASSERT_EQ(event.getType(), AINPUT_EVENT_TYPE_MOTION);
226 EXPECT_EQ(event.getDisplayId(), args.displayId);
227
228 const auto& motionEvent = static_cast<const MotionEvent&>(event);
229 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
230 EXPECT_EQ(motionEvent.getAction(), args.action);
231 EXPECT_EQ(motionEvent.getX(0), point.x);
232 EXPECT_EQ(motionEvent.getY(0), point.y);
233 EXPECT_EQ(motionEvent.getRawX(0), point.x);
234 EXPECT_EQ(motionEvent.getRawY(0), point.y);
235 });
Jackal Guof9696682018-10-05 12:23:23 +0800236 }
237
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700238 void assertFilterInputEventWasNotCalled() {
239 std::scoped_lock lock(mLock);
240 ASSERT_EQ(nullptr, mFilteredEvent);
241 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800242
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800243 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700244 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800245 ASSERT_TRUE(mConfigurationChangedTime)
246 << "Timed out waiting for configuration changed call";
247 ASSERT_EQ(*mConfigurationChangedTime, when);
248 mConfigurationChangedTime = std::nullopt;
249 }
250
251 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700252 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800254 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
256 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
257 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
258 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
259 mLastNotifySwitch = std::nullopt;
260 }
261
chaviwfd6d3512019-03-25 13:23:49 -0700262 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700263 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800264 ASSERT_EQ(touchedToken, mOnPointerDownToken);
265 mOnPointerDownToken.clear();
266 }
267
268 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_TRUE(mOnPointerDownToken == nullptr)
271 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700272 }
273
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700274 // This function must be called soon after the expected ANR timer starts,
275 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500276 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700277 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500278 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800279 std::unique_lock lock(mLock);
280 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800282 ASSERT_NO_FATAL_FAILURE(
283 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700285 }
286
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000287 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 const sp<WindowInfoHandle>& window) {
289 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
290 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
291 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 }
293
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
295 const sp<IBinder>& expectedToken,
296 int32_t expectedPid) {
297 std::unique_lock lock(mLock);
298 android::base::ScopedLockAssertion assumeLocked(mLock);
299 AnrResult result;
300 ASSERT_NO_FATAL_FAILURE(result =
301 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
302 const auto& [token, pid] = result;
303 ASSERT_EQ(expectedToken, token);
304 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500305 }
306
Prabir Pradhanedd96402022-02-15 01:46:16 -0800307 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000308 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500309 std::unique_lock lock(mLock);
310 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800311 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
312 const auto& [token, _] = result;
313 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000314 }
315
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
317 int32_t expectedPid) {
318 std::unique_lock lock(mLock);
319 android::base::ScopedLockAssertion assumeLocked(mLock);
320 AnrResult result;
321 ASSERT_NO_FATAL_FAILURE(
322 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
323 const auto& [token, pid] = result;
324 ASSERT_EQ(expectedToken, token);
325 ASSERT_EQ(expectedPid, pid);
326 }
327
328 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000329 sp<IBinder> getResponsiveWindowToken() {
330 std::unique_lock lock(mLock);
331 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800332 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
333 const auto& [token, _] = result;
334 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700335 }
336
337 void assertNotifyAnrWasNotCalled() {
338 std::scoped_lock lock(mLock);
339 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800340 ASSERT_TRUE(mAnrWindows.empty());
341 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500342 << "ANR was not called, but please also consume the 'connection is responsive' "
343 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700344 }
345
Garfield Tan1c7bc862020-01-28 13:24:04 -0800346 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
347 mConfig.keyRepeatTimeout = timeout;
348 mConfig.keyRepeatDelay = delay;
349 }
350
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000351 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800352 std::unique_lock lock(mLock);
353 base::ScopedLockAssertion assumeLocked(mLock);
354
355 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
356 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800358 enabled;
359 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
361 << ") to be called.";
362 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000364 auto request = *mPointerCaptureRequest;
365 mPointerCaptureRequest.reset();
366 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800367 }
368
369 void assertSetPointerCaptureNotCalled() {
370 std::unique_lock lock(mLock);
371 base::ScopedLockAssertion assumeLocked(mLock);
372
373 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
380
arthurhungf452d0b2021-01-06 00:19:52 +0800381 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
382 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800383 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800384 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800386 }
387
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800388 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391 std::optional<sp<IBinder>> receivedToken =
392 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
393 mNotifyInputChannelBroken);
394 ASSERT_TRUE(receivedToken.has_value());
395 ASSERT_EQ(token, *receivedToken);
396 }
397
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800398 /**
399 * Set policy timeout. A value of zero means next key will not be intercepted.
400 */
401 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
402 mInterceptKeyTimeout = timeout;
403 }
404
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700406 std::mutex mLock;
407 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
408 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
409 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
410 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800411
Prabir Pradhan99987712020-11-10 18:43:05 -0800412 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000413
414 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800415
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700416 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700417 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800418 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
419 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700420 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800421 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
422 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700423
arthurhungf452d0b2021-01-06 00:19:52 +0800424 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800425 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800426
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800427 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
428
Prabir Pradhanedd96402022-02-15 01:46:16 -0800429 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
430 // for a specific container to become non-empty. When the container is non-empty, return the
431 // first entry from the container and erase it.
432 template <class T>
433 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
434 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
435 // If there is an ANR, Dispatcher won't be idle because there are still events
436 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
437 // before checking if ANR was called.
438 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
439 // to provide it some time to act. 100ms seems reasonable.
440 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
441 const std::chrono::time_point start = std::chrono::steady_clock::now();
442 std::optional<T> token =
443 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
444 if (!token.has_value()) {
445 ADD_FAILURE() << "Did not receive the ANR callback";
446 return {};
447 }
448
449 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
450 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
451 // the dispatcher started counting before this function was called
452 if (std::chrono::abs(timeout - waited) > 100ms) {
453 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
454 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
455 << "ms, but waited "
456 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
457 << "ms instead";
458 }
459 return *token;
460 }
461
462 template <class T>
463 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
464 std::queue<T>& storage,
465 std::unique_lock<std::mutex>& lock,
466 std::condition_variable& condition)
467 REQUIRES(mLock) {
468 condition.wait_for(lock, timeout,
469 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
470 if (storage.empty()) {
471 ADD_FAILURE() << "Did not receive the expected callback";
472 return std::nullopt;
473 }
474 T item = storage.front();
475 storage.pop();
476 return std::make_optional(item);
477 }
478
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600479 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700480 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800481 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 }
483
Prabir Pradhanedd96402022-02-15 01:46:16 -0800484 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
485 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700486 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800487 ASSERT_TRUE(pid.has_value());
488 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700489 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500490 }
491
Prabir Pradhanedd96402022-02-15 01:46:16 -0800492 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
493 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500494 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800495 ASSERT_TRUE(pid.has_value());
496 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500497 mNotifyAnr.notify_all();
498 }
499
500 void notifyNoFocusedWindowAnr(
501 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
502 std::scoped_lock lock(mLock);
503 mAnrApplications.push(applicationHandle);
504 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800505 }
506
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800507 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
508 std::scoped_lock lock(mLock);
509 mBrokenInputChannels.push(connectionToken);
510 mNotifyInputChannelBroken.notify_all();
511 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600513 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700514
Chris Yef59a2f42020-10-16 12:55:26 -0700515 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
516 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
517 const std::vector<float>& values) override {}
518
519 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
520 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000521
Chris Yefb552902021-02-03 17:18:37 -0800522 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
523
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600524 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525 *outConfig = mConfig;
526 }
527
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600528 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700529 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800530 switch (inputEvent->getType()) {
531 case AINPUT_EVENT_TYPE_KEY: {
532 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800533 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800534 break;
535 }
536
537 case AINPUT_EVENT_TYPE_MOTION: {
538 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800539 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800540 break;
541 }
542 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800543 return true;
544 }
545
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800546 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
547 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
548 // Clear intercept state when we handled the event.
549 mInterceptKeyTimeout = 0ms;
550 }
551 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600553 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600555 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800556 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
557 // Clear intercept state so we could dispatch the event in next wake.
558 mInterceptKeyTimeout = 0ms;
559 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800560 }
561
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600562 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800563 return false;
564 }
565
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600566 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
567 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700568 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800569 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
570 * essentially a passthrough for notifySwitch.
571 */
Harry Cutts33476232023-01-30 19:57:29 +0000572 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800573 }
574
Sean Stoutb4e0a592021-02-23 07:34:53 -0800575 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600577 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700578 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700579 mOnPointerDownToken = newToken;
580 }
581
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000582 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800583 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000584 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800585 mPointerCaptureChangedCondition.notify_all();
586 }
587
arthurhungf452d0b2021-01-06 00:19:52 +0800588 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
589 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800590 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800591 mDropTargetWindowToken = token;
592 }
593
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700594 void assertFilterInputEventWasCalledInternal(
595 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700596 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800597 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700598 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800599 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800600 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800601};
602
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603// --- InputDispatcherTest ---
604
605class InputDispatcherTest : public testing::Test {
606protected:
607 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700608 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800609
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000610 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700611 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800612 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800613 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000614 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700615 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800616 }
617
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000618 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700619 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700621 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700623
624 /**
625 * Used for debugging when writing the test
626 */
627 void dumpDispatcherState() {
628 std::string dump;
629 mDispatcher->dump(dump);
630 std::stringstream ss(dump);
631 std::string to;
632
633 while (std::getline(ss, to, '\n')) {
634 ALOGE("%s", to.c_str());
635 }
636 }
Vishnu Nair958da932020-08-21 17:12:37 -0700637
chaviw3277faf2021-05-19 16:45:23 -0500638 void setFocusedWindow(const sp<WindowInfoHandle>& window,
639 const sp<WindowInfoHandle>& focusedWindow = nullptr) {
Vishnu Nair958da932020-08-21 17:12:37 -0700640 FocusRequest request;
641 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000642 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700643 if (focusedWindow) {
644 request.focusedToken = focusedWindow->getToken();
645 }
646 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
647 request.displayId = window->getInfo()->displayId;
648 mDispatcher->setFocusedWindow(request);
649 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650};
651
Michael Wrightd02c5b62014-02-10 15:10:22 -0800652TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
653 KeyEvent event;
654
655 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800656 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
657 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600658 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
659 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800660 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000661 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000662 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800663 << "Should reject key events with undefined action.";
664
665 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800666 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
667 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600668 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800669 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000670 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000671 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672 << "Should reject key events with ACTION_MULTIPLE.";
673}
674
675TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
676 MotionEvent event;
677 PointerProperties pointerProperties[MAX_POINTERS + 1];
678 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800679 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800680 pointerProperties[i].clear();
681 pointerProperties[i].id = i;
682 pointerCoords[i].clear();
683 }
684
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800685 // Some constants commonly used below
686 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
687 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
688 constexpr int32_t metaState = AMETA_NONE;
689 constexpr MotionClassification classification = MotionClassification::NONE;
690
chaviw9eaa22c2020-07-01 16:21:27 -0700691 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800692 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700694 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
695 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700696 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
697 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700698 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800699 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000700 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000701 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800702 << "Should reject motion events with undefined action.";
703
704 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800705 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800706 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
707 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
708 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
709 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500710 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800711 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000712 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000713 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714 << "Should reject motion events with pointer down index too large.";
715
Garfield Tanfbe732e2020-01-24 11:26:14 -0800716 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700717 AMOTION_EVENT_ACTION_POINTER_DOWN |
718 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700719 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
720 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700721 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500722 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800723 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000724 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000725 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 << "Should reject motion events with pointer down index too small.";
727
728 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800730 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
731 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
732 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
733 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500734 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000736 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800738 << "Should reject motion events with pointer up index too large.";
739
Garfield Tanfbe732e2020-01-24 11:26:14 -0800740 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700741 AMOTION_EVENT_ACTION_POINTER_UP |
742 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700743 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
744 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700745 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500746 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000748 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000749 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800750 << "Should reject motion events with pointer up index too small.";
751
752 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800753 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
754 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700755 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700756 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
757 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700758 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000760 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000761 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800762 << "Should reject motion events with 0 pointers.";
763
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
765 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700766 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700767 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
768 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700769 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800773 << "Should reject motion events with more than MAX_POINTERS pointers.";
774
775 // Rejects motion events with invalid pointer ids.
776 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800777 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
778 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700779 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700780 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
781 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700782 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with pointer ids less than 0.";
787
788 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800789 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
790 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700791 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700792 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
793 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800795 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000796 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000797 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
799
800 // Rejects motion events with duplicate pointer ids.
801 pointerProperties[0].id = 1;
802 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800803 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
804 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700805 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700806 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
807 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700808 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000811 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800812 << "Should reject motion events with duplicate pointer ids.";
813}
814
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800815/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
816
817TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
818 constexpr nsecs_t eventTime = 20;
Harry Cutts33476232023-01-30 19:57:29 +0000819 NotifyConfigurationChangedArgs args(/*id=*/10, eventTime);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800820 mDispatcher->notifyConfigurationChanged(&args);
821 ASSERT_TRUE(mDispatcher->waitForIdle());
822
823 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
824}
825
826TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000827 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
828 /*switchMask=*/2);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800829 mDispatcher->notifySwitch(&args);
830
831 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
832 args.policyFlags |= POLICY_FLAG_TRUSTED;
833 mFakePolicy->assertNotifySwitchWasCalled(args);
834}
835
Arthur Hungb92218b2018-08-14 12:00:21 +0800836// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700837static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700838// Default input dispatching timeout if there is no focused application or paused window
839// from which to determine an appropriate dispatching timeout.
840static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
841 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
842 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800843
844class FakeApplicationHandle : public InputApplicationHandle {
845public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700846 FakeApplicationHandle() {
847 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700848 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500849 mInfo.dispatchingTimeoutMillis =
850 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700851 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800852 virtual ~FakeApplicationHandle() {}
853
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000854 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700855
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500856 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
857 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700858 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800859};
860
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800861class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800862public:
Garfield Tan15601662020-09-22 15:32:38 -0700863 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800864 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700865 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800866 }
867
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800868 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700869 InputEvent* event;
870 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
871 if (!consumeSeq) {
872 return nullptr;
873 }
874 finishEvent(*consumeSeq);
875 return event;
876 }
877
878 /**
879 * Receive an event without acknowledging it.
880 * Return the sequence number that could later be used to send finished signal.
881 */
882 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800883 uint32_t consumeSeq;
884 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800885
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800886 std::chrono::time_point start = std::chrono::steady_clock::now();
887 status_t status = WOULD_BLOCK;
888 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000889 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800890 &event);
891 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
892 if (elapsed > 100ms) {
893 break;
894 }
895 }
896
897 if (status == WOULD_BLOCK) {
898 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700899 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800900 }
901
902 if (status != OK) {
903 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700904 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 }
906 if (event == nullptr) {
907 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700908 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800909 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 if (outEvent != nullptr) {
911 *outEvent = event;
912 }
913 return consumeSeq;
914 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 /**
917 * To be used together with "receiveEvent" to complete the consumption of an event.
918 */
919 void finishEvent(uint32_t consumeSeq) {
920 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
921 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800922 }
923
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000924 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
925 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
926 ASSERT_EQ(OK, status);
927 }
928
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000929 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
930 std::optional<int32_t> expectedDisplayId,
931 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 InputEvent* event = consume();
933
934 ASSERT_NE(nullptr, event) << mName.c_str()
935 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800936 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700937 << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
Siarhei Vishniakou7feb2ea2019-11-25 15:11:23 -0800938 << " event, got " << inputEventTypeToString(event->getType()) << " event";
Arthur Hungb92218b2018-08-14 12:00:21 +0800939
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000940 if (expectedDisplayId.has_value()) {
941 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
942 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800943
Tiger Huang8664f8c2018-10-11 19:14:35 +0800944 switch (expectedEventType) {
945 case AINPUT_EVENT_TYPE_KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800946 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
947 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000948 if (expectedFlags.has_value()) {
949 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
950 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800951 break;
952 }
953 case AINPUT_EVENT_TYPE_MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800954 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000955 assertMotionAction(expectedAction, motionEvent.getAction());
956
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000957 if (expectedFlags.has_value()) {
958 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
959 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800960 break;
961 }
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100962 case AINPUT_EVENT_TYPE_FOCUS: {
963 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
964 }
Prabir Pradhan99987712020-11-10 18:43:05 -0800965 case AINPUT_EVENT_TYPE_CAPTURE: {
966 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
967 }
Antonio Kantekf16f2832021-09-28 04:39:20 +0000968 case AINPUT_EVENT_TYPE_TOUCH_MODE: {
969 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
970 }
arthurhungb89ccb02020-12-30 16:19:01 +0800971 case AINPUT_EVENT_TYPE_DRAG: {
972 FAIL() << "Use 'consumeDragEvent' for DRAG events";
973 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800974 default: {
975 FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
976 }
977 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800978 }
979
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800980 MotionEvent* consumeMotion() {
981 InputEvent* event = consume();
982
983 if (event == nullptr) {
984 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
985 return nullptr;
986 }
987
988 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
989 ADD_FAILURE() << mName << " expected a MotionEvent, got "
990 << inputEventTypeToString(event->getType()) << " event";
991 return nullptr;
992 }
993 return static_cast<MotionEvent*>(event);
994 }
995
996 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
997 MotionEvent* motionEvent = consumeMotion();
998 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
999 ASSERT_THAT(*motionEvent, matcher);
1000 }
1001
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001002 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1003 InputEvent* event = consume();
1004 ASSERT_NE(nullptr, event) << mName.c_str()
1005 << ": consumer should have returned non-NULL event.";
1006 ASSERT_EQ(AINPUT_EVENT_TYPE_FOCUS, event->getType())
1007 << "Got " << inputEventTypeToString(event->getType())
1008 << " event instead of FOCUS event";
1009
1010 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1011 << mName.c_str() << ": event displayId should always be NONE.";
1012
1013 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1014 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001015 }
1016
Prabir Pradhan99987712020-11-10 18:43:05 -08001017 void consumeCaptureEvent(bool hasCapture) {
1018 const InputEvent* event = consume();
1019 ASSERT_NE(nullptr, event) << mName.c_str()
1020 << ": consumer should have returned non-NULL event.";
1021 ASSERT_EQ(AINPUT_EVENT_TYPE_CAPTURE, event->getType())
1022 << "Got " << inputEventTypeToString(event->getType())
1023 << " event instead of CAPTURE event";
1024
1025 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1026 << mName.c_str() << ": event displayId should always be NONE.";
1027
1028 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1029 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1030 }
1031
arthurhungb89ccb02020-12-30 16:19:01 +08001032 void consumeDragEvent(bool isExiting, float x, float y) {
1033 const InputEvent* event = consume();
1034 ASSERT_NE(nullptr, event) << mName.c_str()
1035 << ": consumer should have returned non-NULL event.";
1036 ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
1037 << "Got " << inputEventTypeToString(event->getType())
1038 << " event instead of DRAG event";
1039
1040 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1041 << mName.c_str() << ": event displayId should always be NONE.";
1042
1043 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1044 EXPECT_EQ(isExiting, dragEvent.isExiting());
1045 EXPECT_EQ(x, dragEvent.getX());
1046 EXPECT_EQ(y, dragEvent.getY());
1047 }
1048
Antonio Kantekf16f2832021-09-28 04:39:20 +00001049 void consumeTouchModeEvent(bool inTouchMode) {
1050 const InputEvent* event = consume();
1051 ASSERT_NE(nullptr, event) << mName.c_str()
1052 << ": consumer should have returned non-NULL event.";
1053 ASSERT_EQ(AINPUT_EVENT_TYPE_TOUCH_MODE, event->getType())
1054 << "Got " << inputEventTypeToString(event->getType())
1055 << " event instead of TOUCH_MODE event";
1056
1057 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1058 << mName.c_str() << ": event displayId should always be NONE.";
1059 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1060 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1061 }
1062
chaviwd1c23182019-12-20 18:44:56 -08001063 void assertNoEvents() {
1064 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001065 if (event == nullptr) {
1066 return;
1067 }
1068 if (event->getType() == AINPUT_EVENT_TYPE_KEY) {
1069 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1070 ADD_FAILURE() << "Received key event "
1071 << KeyEvent::actionToString(keyEvent.getAction());
1072 } else if (event->getType() == AINPUT_EVENT_TYPE_MOTION) {
1073 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1074 ADD_FAILURE() << "Received motion event "
1075 << MotionEvent::actionToString(motionEvent.getAction());
1076 } else if (event->getType() == AINPUT_EVENT_TYPE_FOCUS) {
1077 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1078 ADD_FAILURE() << "Received focus event, hasFocus = "
1079 << (focusEvent.getHasFocus() ? "true" : "false");
Prabir Pradhan99987712020-11-10 18:43:05 -08001080 } else if (event->getType() == AINPUT_EVENT_TYPE_CAPTURE) {
1081 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1082 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1083 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Antonio Kantekf16f2832021-09-28 04:39:20 +00001084 } else if (event->getType() == AINPUT_EVENT_TYPE_TOUCH_MODE) {
1085 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1086 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1087 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001088 }
1089 FAIL() << mName.c_str()
1090 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001091 }
1092
1093 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1094
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001095 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1096
chaviwd1c23182019-12-20 18:44:56 -08001097protected:
1098 std::unique_ptr<InputConsumer> mConsumer;
1099 PreallocatedInputEventFactory mEventFactory;
1100
1101 std::string mName;
1102};
1103
chaviw3277faf2021-05-19 16:45:23 -05001104class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001105public:
1106 static const int32_t WIDTH = 600;
1107 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001108
Chris Yea209fde2020-07-22 13:54:51 -07001109 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001110 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001111 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001112 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001113 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001114 base::Result<std::unique_ptr<InputChannel>> channel =
1115 dispatcher->createInputChannel(name);
1116 token = (*channel)->getConnectionToken();
1117 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001118 }
1119
1120 inputApplicationHandle->updateInfo();
1121 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1122
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001123 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001124 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001125 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001126 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001127 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001128 mInfo.frameLeft = 0;
1129 mInfo.frameTop = 0;
1130 mInfo.frameRight = WIDTH;
1131 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001132 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001133 mInfo.globalScaleFactor = 1.0;
1134 mInfo.touchableRegion.clear();
1135 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001136 mInfo.ownerPid = WINDOW_PID;
1137 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001138 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001139 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001140 }
1141
Arthur Hungabbb9d82021-09-01 14:52:30 +00001142 sp<FakeWindowHandle> clone(
1143 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001144 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001145 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001146 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1147 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001148 return handle;
1149 }
1150
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001151 void setTouchable(bool touchable) {
1152 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1153 }
chaviwd1c23182019-12-20 18:44:56 -08001154
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001155 void setFocusable(bool focusable) {
1156 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1157 }
1158
1159 void setVisible(bool visible) {
1160 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1161 }
Vishnu Nair958da932020-08-21 17:12:37 -07001162
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001163 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001164 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001165 }
1166
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001167 void setPaused(bool paused) {
1168 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1169 }
1170
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001171 void setPreventSplitting(bool preventSplitting) {
1172 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001173 }
1174
1175 void setSlippery(bool slippery) {
1176 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1177 }
1178
1179 void setWatchOutsideTouch(bool watchOutside) {
1180 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1181 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001182
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001183 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1184
1185 void setInterceptsStylus(bool interceptsStylus) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1187 }
1188
1189 void setDropInput(bool dropInput) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1191 }
1192
1193 void setDropInputIfObscured(bool dropInputIfObscured) {
1194 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1195 }
1196
1197 void setNoInputChannel(bool noInputChannel) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1199 }
1200
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001201 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1202
chaviw3277faf2021-05-19 16:45:23 -05001203 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001204
Bernardo Rufino7393d172021-02-26 13:56:11 +00001205 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1206
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001207 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001208 mInfo.frameLeft = frame.left;
1209 mInfo.frameTop = frame.top;
1210 mInfo.frameRight = frame.right;
1211 mInfo.frameBottom = frame.bottom;
1212 mInfo.touchableRegion.clear();
1213 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001214
1215 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1216 ui::Transform translate;
1217 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1218 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001219 }
1220
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001221 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1222
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001223 void setIsWallpaper(bool isWallpaper) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1225 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001226
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001227 void setDupTouchToWallpaper(bool hasWallpaper) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1229 }
chaviwd1c23182019-12-20 18:44:56 -08001230
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001231 void setTrustedOverlay(bool trustedOverlay) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1233 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001234
chaviw9eaa22c2020-07-01 16:21:27 -07001235 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1236 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1237 }
1238
1239 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001240
yunho.shinf4a80b82020-11-16 21:13:57 +09001241 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1242
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001243 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1244 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1245 expectedFlags);
1246 }
1247
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001248 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
1249 consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
1250 }
1251
Svet Ganov5d3bc372020-01-26 23:11:07 -08001252 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001253 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001254 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1255 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001256 }
1257
1258 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001259 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001260 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1261 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 }
1263
1264 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001265 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001266 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1267 }
1268
1269 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1270 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001271 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
1272 expectedFlags);
1273 }
1274
Svet Ganov5d3bc372020-01-26 23:11:07 -08001275 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1277 int32_t expectedFlags = 0) {
1278 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1279 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1281 }
1282
1283 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001284 int32_t expectedFlags = 0) {
1285 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001287 consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, expectedDisplayId, expectedFlags);
1288 }
1289
1290 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
Michael Wright3a240c42019-12-10 20:53:41 +00001292 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
1293 expectedFlags);
1294 }
1295
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001296 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1297 int32_t expectedFlags = 0) {
1298 consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
1299 expectedFlags);
1300 }
1301
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001302 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1303 int32_t expectedFlags = 0) {
1304 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001305 ASSERT_NE(nullptr, event);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001306 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
1307 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1308 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1309 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1310 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1311 }
1312
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001313 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1314 ASSERT_NE(mInputReceiver, nullptr)
1315 << "Cannot consume events from a window with no receiver";
1316 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1317 }
1318
Prabir Pradhan99987712020-11-10 18:43:05 -08001319 void consumeCaptureEvent(bool hasCapture) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeCaptureEvent(hasCapture);
1323 }
1324
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1326 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001327 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001328 ASSERT_THAT(*motionEvent, matcher);
1329 }
1330
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001331 void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
1332 std::optional<int32_t> expectedDisplayId,
1333 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1335 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1336 expectedFlags);
1337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001354 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
chaviwaf87b3e2019-10-01 16:59:28 -07001367 InputEvent* consume() {
1368 if (mInputReceiver == nullptr) {
1369 return nullptr;
1370 }
1371 return mInputReceiver->consume();
1372 }
1373
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 MotionEvent* consumeMotion() {
1375 InputEvent* event = consume();
1376 if (event == nullptr) {
1377 ADD_FAILURE() << "Consume failed : no event";
1378 return nullptr;
1379 }
1380 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
1381 ADD_FAILURE() << "Instead of motion event, got "
1382 << inputEventTypeToString(event->getType());
1383 return nullptr;
1384 }
1385 return static_cast<MotionEvent*>(event);
1386 }
1387
Arthur Hungb92218b2018-08-14 12:00:21 +08001388 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001389 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001390 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001391 return; // Can't receive events if the window does not have input channel
1392 }
1393 ASSERT_NE(nullptr, mInputReceiver)
1394 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001395 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001396 }
1397
chaviwaf87b3e2019-10-01 16:59:28 -07001398 sp<IBinder> getToken() { return mInfo.token; }
1399
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001400 const std::string& getName() { return mName; }
1401
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001402 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1403 mInfo.ownerPid = ownerPid;
1404 mInfo.ownerUid = ownerUid;
1405 }
1406
Prabir Pradhanedd96402022-02-15 01:46:16 -08001407 int32_t getPid() const { return mInfo.ownerPid; }
1408
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001409 void destroyReceiver() { mInputReceiver = nullptr; }
1410
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001411 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1412
chaviwd1c23182019-12-20 18:44:56 -08001413private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001414 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001415 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001416 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001417};
1418
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001419std::atomic<int32_t> FakeWindowHandle::sId{1};
1420
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001421static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001422 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001423 int32_t displayId = ADISPLAY_ID_NONE,
1424 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001425 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001426 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1427 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001428 KeyEvent event;
1429 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1430
1431 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001432 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001433 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1434 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001435
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001436 if (!allowKeyRepeat) {
1437 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1438 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001439 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001440 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001441}
1442
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001443static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001444 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001445 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001446}
1447
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001448// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1449// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1450// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001451static InputEventInjectionResult injectKeyDownNoRepeat(
1452 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001453 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001454 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001455 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001456}
1457
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001458static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001459 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001460 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001461}
1462
Garfield Tandf26e862020-07-01 20:18:19 -07001463class PointerBuilder {
1464public:
1465 PointerBuilder(int32_t id, int32_t toolType) {
1466 mProperties.clear();
1467 mProperties.id = id;
1468 mProperties.toolType = toolType;
1469 mCoords.clear();
1470 }
1471
1472 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1473
1474 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1475
1476 PointerBuilder& axis(int32_t axis, float value) {
1477 mCoords.setAxisValue(axis, value);
1478 return *this;
1479 }
1480
1481 PointerProperties buildProperties() const { return mProperties; }
1482
1483 PointerCoords buildCoords() const { return mCoords; }
1484
1485private:
1486 PointerProperties mProperties;
1487 PointerCoords mCoords;
1488};
1489
1490class MotionEventBuilder {
1491public:
1492 MotionEventBuilder(int32_t action, int32_t source) {
1493 mAction = action;
1494 mSource = source;
1495 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001496 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001497 }
1498
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001499 MotionEventBuilder& deviceId(int32_t deviceId) {
1500 mDeviceId = deviceId;
1501 return *this;
1502 }
1503
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001504 MotionEventBuilder& downTime(nsecs_t downTime) {
1505 mDownTime = downTime;
1506 return *this;
1507 }
1508
Garfield Tandf26e862020-07-01 20:18:19 -07001509 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1510 mEventTime = eventTime;
1511 return *this;
1512 }
1513
1514 MotionEventBuilder& displayId(int32_t displayId) {
1515 mDisplayId = displayId;
1516 return *this;
1517 }
1518
1519 MotionEventBuilder& actionButton(int32_t actionButton) {
1520 mActionButton = actionButton;
1521 return *this;
1522 }
1523
arthurhung6d4bed92021-03-17 11:59:33 +08001524 MotionEventBuilder& buttonState(int32_t buttonState) {
1525 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001526 return *this;
1527 }
1528
1529 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1530 mRawXCursorPosition = rawXCursorPosition;
1531 return *this;
1532 }
1533
1534 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1535 mRawYCursorPosition = rawYCursorPosition;
1536 return *this;
1537 }
1538
1539 MotionEventBuilder& pointer(PointerBuilder pointer) {
1540 mPointers.push_back(pointer);
1541 return *this;
1542 }
1543
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001544 MotionEventBuilder& addFlag(uint32_t flags) {
1545 mFlags |= flags;
1546 return *this;
1547 }
1548
Garfield Tandf26e862020-07-01 20:18:19 -07001549 MotionEvent build() {
1550 std::vector<PointerProperties> pointerProperties;
1551 std::vector<PointerCoords> pointerCoords;
1552 for (const PointerBuilder& pointer : mPointers) {
1553 pointerProperties.push_back(pointer.buildProperties());
1554 pointerCoords.push_back(pointer.buildCoords());
1555 }
1556
1557 // Set mouse cursor position for the most common cases to avoid boilerplate.
1558 if (mSource == AINPUT_SOURCE_MOUSE &&
1559 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1560 mPointers.size() == 1) {
1561 mRawXCursorPosition = pointerCoords[0].getX();
1562 mRawYCursorPosition = pointerCoords[0].getY();
1563 }
1564
1565 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001566 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001567 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001568 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001569 mButtonState, MotionClassification::NONE, identityTransform,
1570 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001571 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001572 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001573
1574 return event;
1575 }
1576
1577private:
1578 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001579 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001580 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001581 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001582 nsecs_t mEventTime;
1583 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1584 int32_t mActionButton{0};
1585 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001586 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001587 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1588 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1589
1590 std::vector<PointerBuilder> mPointers;
1591};
1592
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001593class MotionArgsBuilder {
1594public:
1595 MotionArgsBuilder(int32_t action, int32_t source) {
1596 mAction = action;
1597 mSource = source;
1598 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1599 mDownTime = mEventTime;
1600 }
1601
1602 MotionArgsBuilder& deviceId(int32_t deviceId) {
1603 mDeviceId = deviceId;
1604 return *this;
1605 }
1606
1607 MotionArgsBuilder& downTime(nsecs_t downTime) {
1608 mDownTime = downTime;
1609 return *this;
1610 }
1611
1612 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1613 mEventTime = eventTime;
1614 return *this;
1615 }
1616
1617 MotionArgsBuilder& displayId(int32_t displayId) {
1618 mDisplayId = displayId;
1619 return *this;
1620 }
1621
1622 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1623 mPolicyFlags = policyFlags;
1624 return *this;
1625 }
1626
1627 MotionArgsBuilder& actionButton(int32_t actionButton) {
1628 mActionButton = actionButton;
1629 return *this;
1630 }
1631
1632 MotionArgsBuilder& buttonState(int32_t buttonState) {
1633 mButtonState = buttonState;
1634 return *this;
1635 }
1636
1637 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1638 mRawXCursorPosition = rawXCursorPosition;
1639 return *this;
1640 }
1641
1642 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1643 mRawYCursorPosition = rawYCursorPosition;
1644 return *this;
1645 }
1646
1647 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1648 mPointers.push_back(pointer);
1649 return *this;
1650 }
1651
1652 MotionArgsBuilder& addFlag(uint32_t flags) {
1653 mFlags |= flags;
1654 return *this;
1655 }
1656
1657 NotifyMotionArgs build() {
1658 std::vector<PointerProperties> pointerProperties;
1659 std::vector<PointerCoords> pointerCoords;
1660 for (const PointerBuilder& pointer : mPointers) {
1661 pointerProperties.push_back(pointer.buildProperties());
1662 pointerCoords.push_back(pointer.buildCoords());
1663 }
1664
1665 // Set mouse cursor position for the most common cases to avoid boilerplate.
1666 if (mSource == AINPUT_SOURCE_MOUSE &&
1667 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1668 mPointers.size() == 1) {
1669 mRawXCursorPosition = pointerCoords[0].getX();
1670 mRawYCursorPosition = pointerCoords[0].getY();
1671 }
1672
1673 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1674 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1675 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1676 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1677 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1678 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1679
1680 return args;
1681 }
1682
1683private:
1684 int32_t mAction;
1685 int32_t mDeviceId = DEVICE_ID;
1686 int32_t mSource;
1687 nsecs_t mDownTime;
1688 nsecs_t mEventTime;
1689 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1690 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1691 int32_t mActionButton{0};
1692 int32_t mButtonState{0};
1693 int32_t mFlags{0};
1694 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1695 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1696
1697 std::vector<PointerBuilder> mPointers;
1698};
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, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001702 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001703 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1704 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1705 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1706 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001707}
1708
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001710 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001711 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001712 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001713 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1714 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001715 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001716 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1717 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001718 MotionEvent event = MotionEventBuilder(action, source)
1719 .displayId(displayId)
1720 .eventTime(eventTime)
1721 .rawXCursorPosition(cursorPosition.x)
1722 .rawYCursorPosition(cursorPosition.y)
Harry Cutts33476232023-01-30 19:57:29 +00001723 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001724 .x(position.x)
1725 .y(position.y))
1726 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001727
1728 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001729 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1730 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001731}
1732
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001733static InputEventInjectionResult injectMotionDown(
1734 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1735 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001736 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001737}
1738
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001739static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001740 int32_t source, int32_t displayId,
1741 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001742 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001743}
1744
Jackal Guof9696682018-10-05 12:23:23 +08001745static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1746 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1747 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001748 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001749 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1750 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001751
1752 return args;
1753}
1754
chaviwd1c23182019-12-20 18:44:56 -08001755static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId,
1756 const std::vector<PointF>& points) {
1757 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001758 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1759 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1760 }
1761
chaviwd1c23182019-12-20 18:44:56 -08001762 PointerProperties pointerProperties[pointerCount];
1763 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001764
chaviwd1c23182019-12-20 18:44:56 -08001765 for (size_t i = 0; i < pointerCount; i++) {
1766 pointerProperties[i].clear();
1767 pointerProperties[i].id = i;
1768 pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001769
chaviwd1c23182019-12-20 18:44:56 -08001770 pointerCoords[i].clear();
1771 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1772 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1773 }
Jackal Guof9696682018-10-05 12:23:23 +08001774
1775 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1776 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001777 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001778 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1779 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001780 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1781 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001782 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1783 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001784
1785 return args;
1786}
1787
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001788static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1789 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1790}
1791
chaviwd1c23182019-12-20 18:44:56 -08001792static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1793 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1794}
1795
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001796static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1797 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001798 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001799}
1800
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001801/**
1802 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1803 * broken channel.
1804 */
1805TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1807 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001808 sp<FakeWindowHandle>::make(application, mDispatcher,
1809 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001810
1811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1812
1813 // Window closes its channel, but the window remains.
1814 window->destroyReceiver();
1815 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1816}
1817
Arthur Hungb92218b2018-08-14 12:00:21 +08001818TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1821 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001822
Arthur Hung72d8dc32020-03-28 00:48:39 +00001823 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1825 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001827
1828 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001829 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001830}
1831
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001832TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001834 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1835 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001836
1837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1838 // Inject a MotionEvent to an unknown display.
1839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1840 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1842
1843 // Window should receive motion event.
1844 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1845}
1846
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001847/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001848 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001849 * This test serves as a sanity check for the next test, where setInputWindows is
1850 * called twice.
1851 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001852TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001854 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1855 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001856 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001857
1858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001860 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1861 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001863
1864 // Window should receive motion event.
1865 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1866}
1867
1868/**
1869 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001870 */
1871TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001873 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1874 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001875 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001876
1877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001880 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1881 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001883
1884 // Window should receive motion event.
1885 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1886}
1887
Arthur Hungb92218b2018-08-14 12:00:21 +08001888// The foreground window should receive the first touch down event.
1889TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001891 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001892 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001893 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001894 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001895
Arthur Hung72d8dc32020-03-28 00:48:39 +00001896 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1898 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001900
1901 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001902 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001903 windowSecond->assertNoEvents();
1904}
1905
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001906/**
1907 * Two windows: A top window, and a wallpaper behind the window.
1908 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1909 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001910 * 1. foregroundWindow <-- dup touch to wallpaper
1911 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001912 */
1913TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1914 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1915 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001916 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001917 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001918 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001919 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001920 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001921
1922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1924 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1925 {100, 200}))
1926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1927
1928 // Both foreground window and its wallpaper should receive the touch down
1929 foregroundWindow->consumeMotionDown();
1930 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1931
1932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1933 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1934 ADISPLAY_ID_DEFAULT, {110, 200}))
1935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1936
1937 foregroundWindow->consumeMotionMove();
1938 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1939
1940 // Now the foreground window goes away, but the wallpaper stays
1941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1942 foregroundWindow->consumeMotionCancel();
1943 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1944 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1945}
1946
1947/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001948 * Two fingers down on the window, and lift off the first finger.
1949 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1950 * contains a single pointer.
1951 */
1952TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1954 sp<FakeWindowHandle> window =
1955 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1956
1957 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1958 NotifyMotionArgs args;
1959 // First touch pointer down on right window
1960 mDispatcher->notifyMotion(&(
1961 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1962 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1963 .build()));
1964 // Second touch pointer down
1965 mDispatcher->notifyMotion(&(
1966 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1967
1968 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1969 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100))
1970 .build()));
1971 // First touch pointer lifts. The second one remains down
1972 mDispatcher->notifyMotion(&(
1973 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1974
1975 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
1976 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(110).y(100))
1977 .build()));
1978 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1979 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1980 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1981
1982 // Remove the window. The gesture should be canceled
1983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1984 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1985 window->consumeMotionEvent(
1986 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1987}
1988
1989/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001990 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1991 * with the following differences:
1992 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1993 * clean up the connection.
1994 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1995 * Ensure that there's no crash in the dispatcher.
1996 */
1997TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1999 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002000 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002001 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002002 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002003 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002004 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002005
2006 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2008 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2009 {100, 200}))
2010 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2011
2012 // Both foreground window and its wallpaper should receive the touch down
2013 foregroundWindow->consumeMotionDown();
2014 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2015
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2017 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2018 ADISPLAY_ID_DEFAULT, {110, 200}))
2019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2020
2021 foregroundWindow->consumeMotionMove();
2022 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2023
2024 // Wallpaper closes its channel, but the window remains.
2025 wallpaperWindow->destroyReceiver();
2026 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2027
2028 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2029 // is no longer valid.
2030 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2031 foregroundWindow->consumeMotionCancel();
2032}
2033
Arthur Hungc539dbb2022-12-08 07:45:36 +00002034class ShouldSplitTouchFixture : public InputDispatcherTest,
2035 public ::testing::WithParamInterface<bool> {};
2036INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2037 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002038/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002039 * A single window that receives touch (on top), and a wallpaper window underneath it.
2040 * The top window gets a multitouch gesture.
2041 * Ensure that wallpaper gets the same gesture.
2042 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 sp<FakeWindowHandle> foregroundWindow =
2046 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2047 foregroundWindow->setDupTouchToWallpaper(true);
2048 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002049
2050 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002051 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002052 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002053
Arthur Hungc539dbb2022-12-08 07:45:36 +00002054 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002055
2056 // Touch down on top window
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2058 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2059 {100, 100}))
2060 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2061
2062 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002063 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002064 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2065
2066 // Second finger down on the top window
2067 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002068 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002070 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2071 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002072 .build();
2073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2074 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2075 InputEventInjectionSync::WAIT_FOR_RESULT))
2076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2077
Harry Cutts33476232023-01-30 19:57:29 +00002078 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2079 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002080 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002081
2082 const MotionEvent secondFingerUpEvent =
2083 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2084 .displayId(ADISPLAY_ID_DEFAULT)
2085 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002086 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2087 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088 .build();
2089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2090 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2091 InputEventInjectionSync::WAIT_FOR_RESULT))
2092 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2093 foregroundWindow->consumeMotionPointerUp(0);
2094 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2095
2096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002097 injectMotionEvent(mDispatcher,
2098 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2099 AINPUT_SOURCE_TOUCHSCREEN)
2100 .displayId(ADISPLAY_ID_DEFAULT)
2101 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2102 .pointer(PointerBuilder(/* id */ 1,
2103 AMOTION_EVENT_TOOL_TYPE_FINGER)
2104 .x(100)
2105 .y(100))
2106 .build(),
2107 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2109 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2110 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002111}
2112
2113/**
2114 * Two windows: a window on the left and window on the right.
2115 * A third window, wallpaper, is behind both windows, and spans both top windows.
2116 * The first touch down goes to the left window. A second pointer touches down on the right window.
2117 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2118 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2119 * ACTION_POINTER_DOWN(1).
2120 */
2121TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2122 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2123 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002124 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002125 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002126 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002127
2128 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002129 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002130 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002131 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002132
2133 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002134 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002135 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002136 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002137
2138 mDispatcher->setInputWindows(
2139 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2140
2141 // Touch down on left window
2142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2143 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2144 {100, 100}))
2145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2146
2147 // Both foreground window and its wallpaper should receive the touch down
2148 leftWindow->consumeMotionDown();
2149 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2150
2151 // Second finger down on the right window
2152 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002153 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002154 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002155 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2156 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002157 .build();
2158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2159 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2160 InputEventInjectionSync::WAIT_FOR_RESULT))
2161 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2162
2163 leftWindow->consumeMotionMove();
2164 // Since the touch is split, right window gets ACTION_DOWN
2165 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002166 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002167 expectedWallpaperFlags);
2168
2169 // Now, leftWindow, which received the first finger, disappears.
2170 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2171 leftWindow->consumeMotionCancel();
2172 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2173 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2174
2175 // The pointer that's still down on the right window moves, and goes to the right window only.
2176 // As far as the dispatcher's concerned though, both pointers are still present.
2177 const MotionEvent secondFingerMoveEvent =
2178 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2179 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00002180 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2181 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002182 .build();
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2184 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2185 InputEventInjectionSync::WAIT_FOR_RESULT));
2186 rightWindow->consumeMotionMove();
2187
2188 leftWindow->assertNoEvents();
2189 rightWindow->assertNoEvents();
2190 wallpaperWindow->assertNoEvents();
2191}
2192
Arthur Hungc539dbb2022-12-08 07:45:36 +00002193/**
2194 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2195 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2196 * The right window should receive ACTION_DOWN.
2197 */
2198TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002200 sp<FakeWindowHandle> leftWindow =
2201 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2202 leftWindow->setFrame(Rect(0, 0, 200, 200));
2203 leftWindow->setDupTouchToWallpaper(true);
2204 leftWindow->setSlippery(true);
2205
2206 sp<FakeWindowHandle> rightWindow =
2207 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2208 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002209
2210 sp<FakeWindowHandle> wallpaperWindow =
2211 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2212 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002213
Arthur Hungc539dbb2022-12-08 07:45:36 +00002214 mDispatcher->setInputWindows(
2215 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002216
Arthur Hungc539dbb2022-12-08 07:45:36 +00002217 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2219 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002220 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002222
2223 // Both foreground window and its wallpaper should receive the touch down
2224 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002225 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2226
Arthur Hungc539dbb2022-12-08 07:45:36 +00002227 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002229 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2230 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2232
Arthur Hungc539dbb2022-12-08 07:45:36 +00002233 leftWindow->consumeMotionCancel();
2234 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2235 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002236}
2237
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002238/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002239 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2240 * interactive, it might stop sending this flag.
2241 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2242 * to have a consistent input stream.
2243 *
2244 * Test procedure:
2245 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2246 * DOWN (new gesture).
2247 *
2248 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2249 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2250 *
2251 * We technically just need a single window here, but we are using two windows (spy on top and a
2252 * regular window below) to emulate the actual situation where it happens on the device.
2253 */
2254TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2256 sp<FakeWindowHandle> spyWindow =
2257 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2258 spyWindow->setFrame(Rect(0, 0, 200, 200));
2259 spyWindow->setTrustedOverlay(true);
2260 spyWindow->setSpy(true);
2261
2262 sp<FakeWindowHandle> window =
2263 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2264 window->setFrame(Rect(0, 0, 200, 200));
2265
2266 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2267 const int32_t touchDeviceId = 4;
2268 NotifyMotionArgs args;
2269
2270 // Two pointers down
2271 mDispatcher->notifyMotion(&(
2272 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .policyFlags(DEFAULT_POLICY_FLAGS)
2275 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2276 .build()));
2277
2278 mDispatcher->notifyMotion(&(
2279 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2280 .deviceId(touchDeviceId)
2281 .policyFlags(DEFAULT_POLICY_FLAGS)
2282 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2283 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
2284 .build()));
2285 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2286 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2287 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2288 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2289
2290 // Cancel the current gesture. Send the cancel without the default policy flags.
2291 mDispatcher->notifyMotion(&(
2292 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2293 .deviceId(touchDeviceId)
2294 .policyFlags(0)
2295 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2296 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
2297 .build()));
2298 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2299 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2300
2301 // We don't need to reset the device to reproduce the issue, but the reset event typically
2302 // follows, so we keep it here to model the actual listener behaviour more closely.
2303 NotifyDeviceResetArgs resetArgs;
2304 resetArgs.id = 1; // arbitrary id
2305 resetArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
2306 resetArgs.deviceId = touchDeviceId;
2307 mDispatcher->notifyDeviceReset(&resetArgs);
2308
2309 // Start new gesture
2310 mDispatcher->notifyMotion(&(
2311 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2312 .deviceId(touchDeviceId)
2313 .policyFlags(DEFAULT_POLICY_FLAGS)
2314 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2315 .build()));
2316 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2317 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2318
2319 // No more events
2320 spyWindow->assertNoEvents();
2321 window->assertNoEvents();
2322}
2323
2324/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002325 * Two windows: a window on the left and a window on the right.
2326 * Mouse is hovered from the right window into the left window.
2327 * Next, we tap on the left window, where the cursor was last seen.
2328 * The second tap is done onto the right window.
2329 * The mouse and tap are from two different devices.
2330 * We technically don't need to set the downtime / eventtime for these events, but setting these
2331 * explicitly helps during debugging.
2332 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2333 * In the buggy implementation, a tap on the right window would cause a crash.
2334 */
2335TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2337 sp<FakeWindowHandle> leftWindow =
2338 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2339 leftWindow->setFrame(Rect(0, 0, 200, 200));
2340
2341 sp<FakeWindowHandle> rightWindow =
2342 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2343 rightWindow->setFrame(Rect(200, 0, 400, 200));
2344
2345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2346 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2347 // stale.
2348 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2349 const int32_t mouseDeviceId = 6;
2350 const int32_t touchDeviceId = 4;
2351 // Move the cursor from right
2352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2353 injectMotionEvent(mDispatcher,
2354 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2355 AINPUT_SOURCE_MOUSE)
2356 .deviceId(mouseDeviceId)
2357 .downTime(baseTime + 10)
2358 .eventTime(baseTime + 20)
2359 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2360 .x(300)
2361 .y(100))
2362 .build()));
2363 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2364
2365 // .. to the left window
2366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2367 injectMotionEvent(mDispatcher,
2368 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2369 AINPUT_SOURCE_MOUSE)
2370 .deviceId(mouseDeviceId)
2371 .downTime(baseTime + 10)
2372 .eventTime(baseTime + 30)
2373 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2374 .x(110)
2375 .y(100))
2376 .build()));
2377 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2378 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2379 // Now tap the left window
2380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2381 injectMotionEvent(mDispatcher,
2382 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2383 AINPUT_SOURCE_TOUCHSCREEN)
2384 .deviceId(touchDeviceId)
2385 .downTime(baseTime + 40)
2386 .eventTime(baseTime + 40)
2387 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2388 .x(100)
2389 .y(100))
2390 .build()));
2391 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2392 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2393
2394 // release tap
2395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2396 injectMotionEvent(mDispatcher,
2397 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2398 AINPUT_SOURCE_TOUCHSCREEN)
2399 .deviceId(touchDeviceId)
2400 .downTime(baseTime + 40)
2401 .eventTime(baseTime + 50)
2402 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2403 .x(100)
2404 .y(100))
2405 .build()));
2406 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2407
2408 // Tap the window on the right
2409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2410 injectMotionEvent(mDispatcher,
2411 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2412 AINPUT_SOURCE_TOUCHSCREEN)
2413 .deviceId(touchDeviceId)
2414 .downTime(baseTime + 60)
2415 .eventTime(baseTime + 60)
2416 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2417 .x(300)
2418 .y(100))
2419 .build()));
2420 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2421
2422 // release tap
2423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2424 injectMotionEvent(mDispatcher,
2425 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2426 AINPUT_SOURCE_TOUCHSCREEN)
2427 .deviceId(touchDeviceId)
2428 .downTime(baseTime + 60)
2429 .eventTime(baseTime + 70)
2430 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2431 .x(300)
2432 .y(100))
2433 .build()));
2434 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2435
2436 // No more events
2437 leftWindow->assertNoEvents();
2438 rightWindow->assertNoEvents();
2439}
2440
2441/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002442 * Two windows: a window on the left and a window on the right.
2443 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2444 * down. Then, on the left window, also place second touch pointer down.
2445 * This test tries to reproduce a crash.
2446 * In the buggy implementation, second pointer down on the left window would cause a crash.
2447 */
2448TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2450 sp<FakeWindowHandle> leftWindow =
2451 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2452 leftWindow->setFrame(Rect(0, 0, 200, 200));
2453
2454 sp<FakeWindowHandle> rightWindow =
2455 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2456 rightWindow->setFrame(Rect(200, 0, 400, 200));
2457
2458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2459
2460 const int32_t touchDeviceId = 4;
2461 const int32_t mouseDeviceId = 6;
2462 NotifyMotionArgs args;
2463
2464 // Start hovering over the left window
2465 mDispatcher->notifyMotion(&(
2466 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2467 .deviceId(mouseDeviceId)
2468 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2469 .build()));
2470 leftWindow->consumeMotionEvent(
2471 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2472
2473 // Mouse down on left window
2474 mDispatcher->notifyMotion(&(
2475 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2476 .deviceId(mouseDeviceId)
2477 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2478 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2479 .build()));
2480
2481 leftWindow->consumeMotionEvent(
2482 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2483 leftWindow->consumeMotionEvent(
2484 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2485
2486 mDispatcher->notifyMotion(&(
2487 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2488 .deviceId(mouseDeviceId)
2489 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2490 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2491 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2492 .build()));
2493 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2494
2495 // First touch pointer down on right window
2496 mDispatcher->notifyMotion(&(
2497 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2498 .deviceId(touchDeviceId)
2499 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2500 .build()));
2501 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2502
2503 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2504
2505 // Second touch pointer down on left window
2506 mDispatcher->notifyMotion(&(
2507 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2508 .deviceId(touchDeviceId)
2509 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2510 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
2511 .build()));
2512 leftWindow->consumeMotionEvent(
2513 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2514 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2515 // current implementation.
2516 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2517 rightWindow->consumeMotionEvent(
2518 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2519
2520 leftWindow->assertNoEvents();
2521 rightWindow->assertNoEvents();
2522}
2523
2524/**
2525 * On a single window, use two different devices: mouse and touch.
2526 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2527 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2528 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2529 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2530 * represent a new gesture.
2531 */
2532TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2534 sp<FakeWindowHandle> window =
2535 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2536 window->setFrame(Rect(0, 0, 400, 400));
2537
2538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2539
2540 const int32_t touchDeviceId = 4;
2541 const int32_t mouseDeviceId = 6;
2542 NotifyMotionArgs args;
2543
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002544 // First touch pointer down
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002545 mDispatcher->notifyMotion(&(
2546 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2549 .build()));
2550 // Second touch pointer down
2551 mDispatcher->notifyMotion(&(
2552 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2553 .deviceId(touchDeviceId)
2554 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2555 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2556 .build()));
2557 // First touch pointer lifts. The second one remains down
2558 mDispatcher->notifyMotion(&(
2559 args = MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2560 .deviceId(touchDeviceId)
2561 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2562 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2563 .build()));
2564 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2565 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2566 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2567
2568 // Mouse down. The touch should be canceled
2569 mDispatcher->notifyMotion(&(
2570 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2571 .deviceId(mouseDeviceId)
2572 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2573 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(320).y(100))
2574 .build()));
2575
2576 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002577 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002578 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2579
2580 mDispatcher->notifyMotion(&(
2581 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2584 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2585 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(320).y(100))
2586 .build()));
2587 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2588
2589 // Second touch pointer down.
2590 mDispatcher->notifyMotion(&(
2591 args = MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2592 .deviceId(touchDeviceId)
2593 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(300).y(100))
2594 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(350).y(100))
2595 .build()));
2596 // The pointer_down event should be ignored
2597 window->assertNoEvents();
2598}
2599
2600/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002601 * This test is similar to the test above, but the sequence of injected events is different.
2602 *
2603 * Two windows: a window on the left and a window on the right.
2604 * Mouse is hovered over the left window.
2605 * Next, we tap on the left window, where the cursor was last seen.
2606 *
2607 * After that, we inject one finger down onto the right window, and then a second finger down onto
2608 * the left window.
2609 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2610 * window (first), and then another on the left window (second).
2611 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2612 * In the buggy implementation, second finger down on the left window would cause a crash.
2613 */
2614TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2616 sp<FakeWindowHandle> leftWindow =
2617 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2618 leftWindow->setFrame(Rect(0, 0, 200, 200));
2619
2620 sp<FakeWindowHandle> rightWindow =
2621 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2622 rightWindow->setFrame(Rect(200, 0, 400, 200));
2623
2624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2625
2626 const int32_t mouseDeviceId = 6;
2627 const int32_t touchDeviceId = 4;
2628 // Hover over the left window. Keep the cursor there.
2629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2630 injectMotionEvent(mDispatcher,
2631 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2632 AINPUT_SOURCE_MOUSE)
2633 .deviceId(mouseDeviceId)
2634 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
2635 .x(50)
2636 .y(50))
2637 .build()));
2638 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2639
2640 // Tap on left window
2641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2642 injectMotionEvent(mDispatcher,
2643 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2644 AINPUT_SOURCE_TOUCHSCREEN)
2645 .deviceId(touchDeviceId)
2646 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2647 .x(100)
2648 .y(100))
2649 .build()));
2650
2651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2652 injectMotionEvent(mDispatcher,
2653 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2654 AINPUT_SOURCE_TOUCHSCREEN)
2655 .deviceId(touchDeviceId)
2656 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2657 .x(100)
2658 .y(100))
2659 .build()));
2660 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2661 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2662 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2663
2664 // First finger down on right window
2665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2666 injectMotionEvent(mDispatcher,
2667 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2668 AINPUT_SOURCE_TOUCHSCREEN)
2669 .deviceId(touchDeviceId)
2670 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2671 .x(300)
2672 .y(100))
2673 .build()));
2674 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2675
2676 // Second finger down on the left window
2677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2678 injectMotionEvent(mDispatcher,
2679 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2680 .deviceId(touchDeviceId)
2681 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2682 .x(300)
2683 .y(100))
2684 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER)
2685 .x(100)
2686 .y(100))
2687 .build()));
2688 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2689 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2690
2691 // No more events
2692 leftWindow->assertNoEvents();
2693 rightWindow->assertNoEvents();
2694}
2695
2696/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002697 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2698 * While the touch is down, new hover events from the stylus device should be ignored. After the
2699 * touch is gone, stylus hovering should start working again.
2700 */
2701TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2703 sp<FakeWindowHandle> window =
2704 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2705 window->setFrame(Rect(0, 0, 200, 200));
2706
2707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2708
2709 const int32_t stylusDeviceId = 5;
2710 const int32_t touchDeviceId = 4;
2711 // Start hovering with stylus
2712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2713 injectMotionEvent(mDispatcher,
2714 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2715 AINPUT_SOURCE_STYLUS)
2716 .deviceId(stylusDeviceId)
2717 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2718 .x(50)
2719 .y(50))
2720 .build()));
2721 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2722
2723 // Finger down on the window
2724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2725 injectMotionEvent(mDispatcher,
2726 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2727 AINPUT_SOURCE_TOUCHSCREEN)
2728 .deviceId(touchDeviceId)
2729 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2730 .x(100)
2731 .y(100))
2732 .build()));
2733 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2734 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2735
2736 // Try to continue hovering with stylus. Since we are already down, injection should fail
2737 ASSERT_EQ(InputEventInjectionResult::FAILED,
2738 injectMotionEvent(mDispatcher,
2739 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2740 AINPUT_SOURCE_STYLUS)
2741 .deviceId(stylusDeviceId)
2742 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2743 .x(50)
2744 .y(50))
2745 .build()));
2746 // No event should be sent. This event should be ignored because a pointer from another device
2747 // is already down.
2748
2749 // Lift up the finger
2750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2751 injectMotionEvent(mDispatcher,
2752 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2753 AINPUT_SOURCE_TOUCHSCREEN)
2754 .deviceId(touchDeviceId)
2755 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
2756 .x(100)
2757 .y(100))
2758 .build()));
2759 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2760
2761 // Now that the touch is gone, stylus hovering should start working again
2762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2763 injectMotionEvent(mDispatcher,
2764 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2765 AINPUT_SOURCE_STYLUS)
2766 .deviceId(stylusDeviceId)
2767 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
2768 .x(50)
2769 .y(50))
2770 .build()));
2771 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2772 // No more events
2773 window->assertNoEvents();
2774}
2775
2776/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002777 * A spy window above a window with no input channel.
2778 * Start hovering with a stylus device, and then tap with it.
2779 * Ensure spy window receives the entire sequence.
2780 */
2781TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2783 sp<FakeWindowHandle> spyWindow =
2784 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2785 spyWindow->setFrame(Rect(0, 0, 200, 200));
2786 spyWindow->setTrustedOverlay(true);
2787 spyWindow->setSpy(true);
2788 sp<FakeWindowHandle> window =
2789 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2790 window->setNoInputChannel(true);
2791 window->setFrame(Rect(0, 0, 200, 200));
2792
2793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2794
2795 NotifyMotionArgs args;
2796
2797 // Start hovering with stylus
2798 mDispatcher->notifyMotion(
2799 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2800 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2801 .build()));
2802 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2803 // Stop hovering
2804 mDispatcher->notifyMotion(
2805 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2806 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2807 .build()));
2808 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2809
2810 // Stylus touches down
2811 mDispatcher->notifyMotion(
2812 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2813 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2814 .build()));
2815 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2816
2817 // Stylus goes up
2818 mDispatcher->notifyMotion(
2819 &(args = MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2820 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2821 .build()));
2822 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2823
2824 // Again hover
2825 mDispatcher->notifyMotion(
2826 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2827 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2828 .build()));
2829 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2830 // Stop hovering
2831 mDispatcher->notifyMotion(
2832 &(args = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2833 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS).x(50).y(50))
2834 .build()));
2835 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2836
2837 // No more events
2838 spyWindow->assertNoEvents();
2839 window->assertNoEvents();
2840}
2841
2842/**
2843 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2844 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2845 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2846 * While the mouse is down, new move events from the touch device should be ignored.
2847 */
2848TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2850 sp<FakeWindowHandle> spyWindow =
2851 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2852 spyWindow->setFrame(Rect(0, 0, 200, 200));
2853 spyWindow->setTrustedOverlay(true);
2854 spyWindow->setSpy(true);
2855 sp<FakeWindowHandle> window =
2856 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2857 window->setFrame(Rect(0, 0, 200, 200));
2858
2859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2860
2861 const int32_t mouseDeviceId = 7;
2862 const int32_t touchDeviceId = 4;
2863 NotifyMotionArgs args;
2864
2865 // Hover a bit with mouse first
2866 mDispatcher->notifyMotion(&(
2867 args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2868 .deviceId(mouseDeviceId)
2869 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2870 .build()));
2871 spyWindow->consumeMotionEvent(
2872 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2873 window->consumeMotionEvent(
2874 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2875
2876 // Start touching
2877 mDispatcher->notifyMotion(
2878 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2879 .deviceId(touchDeviceId)
2880 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
2881 .build()));
2882 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2883 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2884 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2885 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2886
2887 mDispatcher->notifyMotion(
2888 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2889 .deviceId(touchDeviceId)
2890 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(55).y(55))
2891 .build()));
2892 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2893 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2894
2895 // Pilfer the stream
2896 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2897 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2898
2899 mDispatcher->notifyMotion(
2900 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2901 .deviceId(touchDeviceId)
2902 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
2903 .build()));
2904 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2905
2906 // Mouse down
2907 mDispatcher->notifyMotion(&(
2908 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2909 .deviceId(mouseDeviceId)
2910 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2911 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2912 .build()));
2913
2914 spyWindow->consumeMotionEvent(
2915 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2916 spyWindow->consumeMotionEvent(
2917 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2918 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2919
2920 mDispatcher->notifyMotion(&(
2921 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2922 .deviceId(mouseDeviceId)
2923 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2924 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2925 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(100).y(100))
2926 .build()));
2927 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2928 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2929
2930 // Mouse move!
2931 mDispatcher->notifyMotion(&(
2932 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2933 .deviceId(mouseDeviceId)
2934 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2935 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(110).y(110))
2936 .build()));
2937 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2938 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2939
2940 // Touch move!
2941 mDispatcher->notifyMotion(
2942 &(args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2943 .deviceId(touchDeviceId)
2944 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(65).y(65))
2945 .build()));
2946
2947 // No more events
2948 spyWindow->assertNoEvents();
2949 window->assertNoEvents();
2950}
2951
2952/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002953 * On the display, have a single window, and also an area where there's no window.
2954 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2955 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2956 */
2957TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2958 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2959 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002960 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002961
2962 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
2963 NotifyMotionArgs args;
2964
2965 // Touch down on the empty space
2966 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}})));
2967
2968 mDispatcher->waitForIdle();
2969 window->assertNoEvents();
2970
2971 // Now touch down on the window with another pointer
2972 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}})));
2973 mDispatcher->waitForIdle();
2974 window->consumeMotionDown();
2975}
2976
2977/**
2978 * Same test as above, but instead of touching the empty space, the first touch goes to
2979 * non-touchable window.
2980 */
2981TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2982 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2983 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002984 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002985 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2986 window1->setTouchable(false);
2987 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002988 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002989 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2990
2991 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2992
2993 NotifyMotionArgs args;
2994 // Touch down on the non-touchable window
2995 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
2996
2997 mDispatcher->waitForIdle();
2998 window1->assertNoEvents();
2999 window2->assertNoEvents();
3000
3001 // Now touch down on the window with another pointer
3002 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
3003 mDispatcher->waitForIdle();
3004 window2->consumeMotionDown();
3005}
3006
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003007/**
3008 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3009 * to the event time of the first ACTION_DOWN sent to the particular window.
3010 */
3011TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3013 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003014 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003015 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3016 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003017 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003018 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3019
3020 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3021
3022 NotifyMotionArgs args;
3023 // Touch down on the first window
3024 mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
3025
3026 mDispatcher->waitForIdle();
3027 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003028 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003029 window2->assertNoEvents();
3030 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3031 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3032 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3033
3034 // Now touch down on the window with another pointer
3035 mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
3036 mDispatcher->waitForIdle();
3037 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003038 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003039 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3040 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3041 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3042 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3043
3044 // Now move the pointer on the second window
3045 mDispatcher->notifyMotion(
3046 &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
3047 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003048 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003049
3050 // Now add new touch down on the second window
3051 mDispatcher->notifyMotion(
3052 &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
3053 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003054 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003055
3056 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3057 window1->consumeMotionMove();
3058 window1->assertNoEvents();
3059
3060 // Now move the pointer on the first window
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08003061 mDispatcher->notifyMotion(&(
3062 args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}})));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003063 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003064 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003065
3066 mDispatcher->notifyMotion(&(
3067 args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
3068 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003069 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003070}
3071
Garfield Tandf26e862020-07-01 20:18:19 -07003072TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003074 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003075 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003076 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003077 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003078 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003079 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003080
3081 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3082
3083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3084
3085 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003087 injectMotionEvent(mDispatcher,
3088 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3089 AINPUT_SOURCE_MOUSE)
3090 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3091 .x(900)
3092 .y(400))
3093 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003094 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003095
3096 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003098 injectMotionEvent(mDispatcher,
3099 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3100 AINPUT_SOURCE_MOUSE)
3101 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3102 .x(300)
3103 .y(400))
3104 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003105 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3106 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003107
3108 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003110 injectMotionEvent(mDispatcher,
3111 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3112 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3113 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3114 .x(300)
3115 .y(400))
3116 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3118 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003119
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003120 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003121 injectMotionEvent(mDispatcher,
3122 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3123 AINPUT_SOURCE_MOUSE)
3124 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3125 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3126 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3127 .x(300)
3128 .y(400))
3129 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003130 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003131
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003133 injectMotionEvent(mDispatcher,
3134 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3135 AINPUT_SOURCE_MOUSE)
3136 .buttonState(0)
3137 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3138 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3139 .x(300)
3140 .y(400))
3141 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003142 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003143
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003145 injectMotionEvent(mDispatcher,
3146 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3147 .buttonState(0)
3148 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3149 .x(300)
3150 .y(400))
3151 .build()));
3152 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3153
3154 // Move mouse cursor back to right window
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_HOVER_MOVE,
3158 AINPUT_SOURCE_MOUSE)
3159 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3160 .x(900)
3161 .y(400))
3162 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003163 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003164
3165 // No more events
3166 windowLeft->assertNoEvents();
3167 windowRight->assertNoEvents();
3168}
3169
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003170/**
3171 * Put two fingers down (and don't release them) and click the mouse button.
3172 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3173 * currently active gesture should be canceled, and the new one should proceed.
3174 */
3175TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3177 sp<FakeWindowHandle> window =
3178 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3179 window->setFrame(Rect(0, 0, 600, 800));
3180
3181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3182
3183 const int32_t touchDeviceId = 4;
3184 const int32_t mouseDeviceId = 6;
3185 NotifyMotionArgs args;
3186
3187 // Two pointers down
3188 mDispatcher->notifyMotion(&(
3189 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
3192 .build()));
3193
3194 mDispatcher->notifyMotion(&(
3195 args = MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3196 .deviceId(touchDeviceId)
3197 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(100))
3198 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(120).y(120))
3199 .build()));
3200 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3201 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3202
3203 // Inject a series of mouse events for a mouse click
3204 mDispatcher->notifyMotion(&(
3205 args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3206 .deviceId(mouseDeviceId)
3207 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3208 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(300).y(400))
3209 .build()));
3210 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3211 WithPointerCount(2u)));
3212 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3213
3214 mDispatcher->notifyMotion(&(
3215 args = MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3216 .deviceId(mouseDeviceId)
3217 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3218 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3219 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(300).y(400))
3220 .build()));
3221 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3222
3223 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3224 // already canceled gesture, it should be ignored.
3225 mDispatcher->notifyMotion(&(
3226 args = MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3227 .deviceId(touchDeviceId)
3228 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(101).y(101))
3229 .pointer(PointerBuilder(1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(121).y(121))
3230 .build()));
3231 window->assertNoEvents();
3232}
3233
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003234TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3236
3237 sp<FakeWindowHandle> spyWindow =
3238 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3239 spyWindow->setFrame(Rect(0, 0, 600, 800));
3240 spyWindow->setTrustedOverlay(true);
3241 spyWindow->setSpy(true);
3242 sp<FakeWindowHandle> window =
3243 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3244 window->setFrame(Rect(0, 0, 600, 800));
3245
3246 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3247 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3248
3249 // Send mouse cursor to the window
3250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3251 injectMotionEvent(mDispatcher,
3252 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3253 AINPUT_SOURCE_MOUSE)
3254 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3255 .x(100)
3256 .y(100))
3257 .build()));
3258
3259 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3260 WithSource(AINPUT_SOURCE_MOUSE)));
3261 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3262 WithSource(AINPUT_SOURCE_MOUSE)));
3263
3264 window->assertNoEvents();
3265 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003266}
3267
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003268TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3270
3271 sp<FakeWindowHandle> spyWindow =
3272 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3273 spyWindow->setFrame(Rect(0, 0, 600, 800));
3274 spyWindow->setTrustedOverlay(true);
3275 spyWindow->setSpy(true);
3276 sp<FakeWindowHandle> window =
3277 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3278 window->setFrame(Rect(0, 0, 600, 800));
3279
3280 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3282
3283 // Send mouse cursor to the window
3284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3285 injectMotionEvent(mDispatcher,
3286 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3287 AINPUT_SOURCE_MOUSE)
3288 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3289 .x(100)
3290 .y(100))
3291 .build()));
3292
3293 // Move mouse cursor
3294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3295 injectMotionEvent(mDispatcher,
3296 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3297 AINPUT_SOURCE_MOUSE)
3298 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3299 .x(110)
3300 .y(110))
3301 .build()));
3302
3303 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3304 WithSource(AINPUT_SOURCE_MOUSE)));
3305 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3306 WithSource(AINPUT_SOURCE_MOUSE)));
3307 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3308 WithSource(AINPUT_SOURCE_MOUSE)));
3309 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3310 WithSource(AINPUT_SOURCE_MOUSE)));
3311 // Touch down on the window
3312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3313 injectMotionEvent(mDispatcher,
3314 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3315 AINPUT_SOURCE_TOUCHSCREEN)
3316 .deviceId(SECOND_DEVICE_ID)
3317 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3318 .x(200)
3319 .y(200))
3320 .build()));
3321 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3322 WithSource(AINPUT_SOURCE_MOUSE)));
3323 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3324 WithSource(AINPUT_SOURCE_MOUSE)));
3325 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3326 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3327 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3328 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3329
3330 // pilfer the motion, retaining the gesture on the spy window.
3331 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3332 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3333 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3334
3335 // Touch UP on the window
3336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3337 injectMotionEvent(mDispatcher,
3338 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3339 AINPUT_SOURCE_TOUCHSCREEN)
3340 .deviceId(SECOND_DEVICE_ID)
3341 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3342 .x(200)
3343 .y(200))
3344 .build()));
3345 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3346 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3347
3348 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3349 // to send a new gesture. It should again go to both windows (spy and the window below), just
3350 // like the first gesture did, before pilfering. The window configuration has not changed.
3351
3352 // One more tap - DOWN
3353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3354 injectMotionEvent(mDispatcher,
3355 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3356 AINPUT_SOURCE_TOUCHSCREEN)
3357 .deviceId(SECOND_DEVICE_ID)
3358 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3359 .x(250)
3360 .y(250))
3361 .build()));
3362 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3363 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3364 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3365 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3366
3367 // Touch UP on the window
3368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3369 injectMotionEvent(mDispatcher,
3370 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3371 AINPUT_SOURCE_TOUCHSCREEN)
3372 .deviceId(SECOND_DEVICE_ID)
3373 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
3374 .x(250)
3375 .y(250))
3376 .build()));
3377 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3378 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3379 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3380 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3381
3382 window->assertNoEvents();
3383 spyWindow->assertNoEvents();
3384}
3385
Garfield Tandf26e862020-07-01 20:18:19 -07003386// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3387// directly in this test.
3388TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003389 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003390 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003391 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003392 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003393
3394 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3395
3396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3397
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003399 injectMotionEvent(mDispatcher,
3400 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3401 AINPUT_SOURCE_MOUSE)
3402 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3403 .x(300)
3404 .y(400))
3405 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003406 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003407 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003409 injectMotionEvent(mDispatcher,
3410 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3411 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3412 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3413 .x(300)
3414 .y(400))
3415 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003416 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3417 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003418
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003420 injectMotionEvent(mDispatcher,
3421 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3422 AINPUT_SOURCE_MOUSE)
3423 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3424 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3425 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3426 .x(300)
3427 .y(400))
3428 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003429 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003430
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003432 injectMotionEvent(mDispatcher,
3433 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3434 AINPUT_SOURCE_MOUSE)
3435 .buttonState(0)
3436 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3437 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3438 .x(300)
3439 .y(400))
3440 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003441 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003442
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003444 injectMotionEvent(mDispatcher,
3445 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3446 .buttonState(0)
3447 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3448 .x(300)
3449 .y(400))
3450 .build()));
3451 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3452
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003454 injectMotionEvent(mDispatcher,
3455 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3456 AINPUT_SOURCE_MOUSE)
3457 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3458 .x(300)
3459 .y(400))
3460 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003461 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003462}
3463
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003464/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003465 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3466 * is generated.
3467 */
3468TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3470 sp<FakeWindowHandle> window =
3471 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3472 window->setFrame(Rect(0, 0, 1200, 800));
3473
3474 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3475
3476 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3477
3478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3479 injectMotionEvent(mDispatcher,
3480 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3481 AINPUT_SOURCE_MOUSE)
3482 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3483 .x(300)
3484 .y(400))
3485 .build()));
3486 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3487
3488 // Remove the window, but keep the channel.
3489 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3490 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3491}
3492
3493/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003494 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3495 */
3496TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3497 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3498 sp<FakeWindowHandle> window =
3499 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3500 window->setFrame(Rect(0, 0, 100, 100));
3501
3502 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3503
3504 const int32_t mouseDeviceId = 7;
3505 const int32_t touchDeviceId = 4;
3506 NotifyMotionArgs args;
3507
3508 // Start hovering with the mouse
3509 mDispatcher->notifyMotion(
3510 &(args = MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3511 .deviceId(mouseDeviceId)
3512 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE).x(10).y(10))
3513 .build()));
3514 window->consumeMotionEvent(
3515 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3516
3517 // Touch goes down
3518 mDispatcher->notifyMotion(
3519 &(args = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3520 .deviceId(touchDeviceId)
3521 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
3522 .build()));
3523
3524 window->consumeMotionEvent(
3525 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3526 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3527}
3528
3529/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003530 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003531 * The tap causes a HOVER_EXIT event to be generated because the current event
3532 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003533 */
3534TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3536 sp<FakeWindowHandle> window =
3537 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3538 window->setFrame(Rect(0, 0, 100, 100));
3539
3540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3541
3542 // Inject a hover_move from mouse.
3543 NotifyMotionArgs motionArgs =
3544 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3545 ADISPLAY_ID_DEFAULT, {{50, 50}});
3546 motionArgs.xCursorPosition = 50;
3547 motionArgs.yCursorPosition = 50;
3548 mDispatcher->notifyMotion(&motionArgs);
3549 ASSERT_NO_FATAL_FAILURE(
3550 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3551 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003552
3553 // Tap on the window
3554 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3555 ADISPLAY_ID_DEFAULT, {{10, 10}});
3556 mDispatcher->notifyMotion(&motionArgs);
3557 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003558 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3559 WithSource(AINPUT_SOURCE_MOUSE))));
3560
3561 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003562 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3563 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3564
3565 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3566 ADISPLAY_ID_DEFAULT, {{10, 10}});
3567 mDispatcher->notifyMotion(&motionArgs);
3568 ASSERT_NO_FATAL_FAILURE(
3569 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3570 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3571}
3572
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003573TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3575 sp<FakeWindowHandle> windowDefaultDisplay =
3576 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3577 ADISPLAY_ID_DEFAULT);
3578 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3579 sp<FakeWindowHandle> windowSecondDisplay =
3580 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3581 SECOND_DISPLAY_ID);
3582 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3583
3584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3585 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3586
3587 // Set cursor position in window in default display and check that hover enter and move
3588 // events are generated.
3589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3590 injectMotionEvent(mDispatcher,
3591 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3592 AINPUT_SOURCE_MOUSE)
3593 .displayId(ADISPLAY_ID_DEFAULT)
3594 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3595 .x(300)
3596 .y(600))
3597 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003598 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003599
3600 // Remove all windows in secondary display and check that no event happens on window in
3601 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003602 mDispatcher->setInputWindows(
3603 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003604 windowDefaultDisplay->assertNoEvents();
3605
3606 // Move cursor position in window in default display and check that only hover move
3607 // event is generated and not hover enter event.
3608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3609 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3611 injectMotionEvent(mDispatcher,
3612 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3613 AINPUT_SOURCE_MOUSE)
3614 .displayId(ADISPLAY_ID_DEFAULT)
3615 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
3616 .x(400)
3617 .y(700))
3618 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003619 windowDefaultDisplay->consumeMotionEvent(
3620 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3621 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003622 windowDefaultDisplay->assertNoEvents();
3623}
3624
Garfield Tan00f511d2019-06-12 16:55:40 -07003625TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003627
3628 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003629 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003630 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003631 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003632 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003633 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003634
3635 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3636
Arthur Hung72d8dc32020-03-28 00:48:39 +00003637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003638
3639 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3640 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003642 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003643 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003644 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003645 windowRight->assertNoEvents();
3646}
3647
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003648TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003650 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3651 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003652 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003653
Arthur Hung72d8dc32020-03-28 00:48:39 +00003654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003655 setFocusedWindow(window);
3656
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003657 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003658
3659 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3660 mDispatcher->notifyKey(&keyArgs);
3661
3662 // Window should receive key down event.
3663 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3664
3665 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3666 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003667 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003668 mDispatcher->notifyDeviceReset(&args);
3669 window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
3670 AKEY_EVENT_FLAG_CANCELED);
3671}
3672
3673TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003675 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3676 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003677
Arthur Hung72d8dc32020-03-28 00:48:39 +00003678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003679
3680 NotifyMotionArgs motionArgs =
3681 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3682 ADISPLAY_ID_DEFAULT);
3683 mDispatcher->notifyMotion(&motionArgs);
3684
3685 // Window should receive motion down event.
3686 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3687
3688 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3689 // on the app side.
Harry Cutts33476232023-01-30 19:57:29 +00003690 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003691 mDispatcher->notifyDeviceReset(&args);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003692 window->consumeMotionEvent(
3693 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003694}
3695
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003696TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003698 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3699 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003700 window->setFocusable(true);
3701
3702 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3703 setFocusedWindow(window);
3704
3705 window->consumeFocusEvent(true);
3706
3707 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3708 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3709 const nsecs_t injectTime = keyArgs.eventTime;
3710 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
3711 mDispatcher->notifyKey(&keyArgs);
3712 // The dispatching time should be always greater than or equal to intercept key timeout.
3713 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3714 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3715 std::chrono::nanoseconds(interceptKeyTimeout).count());
3716}
3717
3718TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3719 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3721 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003722 window->setFocusable(true);
3723
3724 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3725 setFocusedWindow(window);
3726
3727 window->consumeFocusEvent(true);
3728
3729 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3730 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3731 mFakePolicy->setInterceptKeyTimeout(150ms);
3732 mDispatcher->notifyKey(&keyDown);
3733 mDispatcher->notifyKey(&keyUp);
3734
3735 // Window should receive key event immediately when same key up.
3736 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3737 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3738}
3739
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003740/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003741 * Two windows. First is a regular window. Second does not overlap with the first, and has
3742 * WATCH_OUTSIDE_TOUCH.
3743 * Both windows are owned by the same UID.
3744 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3745 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3746 */
3747TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3750 "First Window", ADISPLAY_ID_DEFAULT);
3751 window->setFrame(Rect{0, 0, 100, 100});
3752
3753 sp<FakeWindowHandle> outsideWindow =
3754 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3755 ADISPLAY_ID_DEFAULT);
3756 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3757 outsideWindow->setWatchOutsideTouch(true);
3758 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3760
3761 // Tap on first window.
3762 NotifyMotionArgs motionArgs =
3763 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3764 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
3765 mDispatcher->notifyMotion(&motionArgs);
3766 window->consumeMotionDown();
3767 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3768 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3769 outsideWindow->consumeMotionEvent(
3770 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3771}
3772
3773/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003774 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3775 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3776 * ACTION_OUTSIDE event is sent per gesture.
3777 */
3778TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3779 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003781 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3782 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003783 window->setWatchOutsideTouch(true);
3784 window->setFrame(Rect{0, 0, 100, 100});
3785 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003786 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3787 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003788 secondWindow->setFrame(Rect{100, 100, 200, 200});
3789 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003790 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3791 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003792 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3794
3795 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
3796 NotifyMotionArgs motionArgs =
3797 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3798 ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
3799 mDispatcher->notifyMotion(&motionArgs);
3800 window->assertNoEvents();
3801 secondWindow->assertNoEvents();
3802
3803 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3804 // Now, `window` should get ACTION_OUTSIDE.
3805 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3806 {PointF{-10, -10}, PointF{105, 105}});
3807 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003808 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3809 window->consumeMotionEvent(
3810 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003811 secondWindow->consumeMotionDown();
3812 thirdWindow->assertNoEvents();
3813
3814 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3815 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
3816 motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3817 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
3818 mDispatcher->notifyMotion(&motionArgs);
3819 window->assertNoEvents();
3820 secondWindow->consumeMotionMove();
3821 thirdWindow->consumeMotionDown();
3822}
3823
Prabir Pradhan814fe082022-07-22 20:22:18 +00003824TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003826 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3827 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003828 window->setFocusable(true);
3829
3830 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3831 setFocusedWindow(window);
3832
3833 window->consumeFocusEvent(true);
3834
3835 NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3836 NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3837 mDispatcher->notifyKey(&keyDown);
3838 mDispatcher->notifyKey(&keyUp);
3839
3840 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3841 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3842
3843 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3844 mDispatcher->onWindowInfosChanged({}, {});
3845
3846 window->consumeFocusEvent(false);
3847
3848 mDispatcher->notifyKey(&keyDown);
3849 mDispatcher->notifyKey(&keyUp);
3850 window->assertNoEvents();
3851}
3852
Arthur Hung96483742022-11-15 03:30:48 +00003853TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3856 "Fake Window", ADISPLAY_ID_DEFAULT);
3857 // Ensure window is non-split and have some transform.
3858 window->setPreventSplitting(true);
3859 window->setWindowOffset(20, 40);
3860 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3861
3862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3863 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3864 {50, 50}))
3865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3866 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3867
3868 const MotionEvent secondFingerDownEvent =
3869 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3870 .displayId(ADISPLAY_ID_DEFAULT)
3871 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00003872 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
3873 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003874 .build();
3875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3876 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3877 InputEventInjectionSync::WAIT_FOR_RESULT))
3878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3879
3880 const MotionEvent* event = window->consumeMotion();
3881 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3882 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3883 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3884 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3885 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3886}
3887
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003888/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003889 * Ensure the correct coordinate spaces are used by InputDispatcher.
3890 *
3891 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3892 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3893 * space.
3894 */
3895class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3896public:
3897 void SetUp() override {
3898 InputDispatcherTest::SetUp();
3899 mDisplayInfos.clear();
3900 mWindowInfos.clear();
3901 }
3902
3903 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3904 gui::DisplayInfo info;
3905 info.displayId = displayId;
3906 info.transform = transform;
3907 mDisplayInfos.push_back(std::move(info));
3908 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3909 }
3910
3911 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3912 mWindowInfos.push_back(*windowHandle->getInfo());
3913 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3914 }
3915
3916 // Set up a test scenario where the display has a scaled projection and there are two windows
3917 // on the display.
3918 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3919 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3920 // respectively.
3921 ui::Transform displayTransform;
3922 displayTransform.set(2, 0, 0, 4);
3923 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3924
3925 std::shared_ptr<FakeApplicationHandle> application =
3926 std::make_shared<FakeApplicationHandle>();
3927
3928 // Add two windows to the display. Their frames are represented in the display space.
3929 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003930 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3931 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003932 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3933 addWindow(firstWindow);
3934
3935 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003936 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3937 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003938 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3939 addWindow(secondWindow);
3940 return {std::move(firstWindow), std::move(secondWindow)};
3941 }
3942
3943private:
3944 std::vector<gui::DisplayInfo> mDisplayInfos;
3945 std::vector<gui::WindowInfo> mWindowInfos;
3946};
3947
3948TEST_F(InputDispatcherDisplayProjectionTest, HitTestsInDisplaySpace) {
3949 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3950 // Send down to the first window. The point is represented in the display space. The point is
3951 // selected so that if the hit test was done with the transform applied to it, then it would
3952 // end up in the incorrect window.
3953 NotifyMotionArgs downMotionArgs =
3954 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3955 ADISPLAY_ID_DEFAULT, {PointF{75, 55}});
3956 mDispatcher->notifyMotion(&downMotionArgs);
3957
3958 firstWindow->consumeMotionDown();
3959 secondWindow->assertNoEvents();
3960}
3961
3962// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3963// the event should be treated as being in the logical display space.
3964TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3965 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3966 // Send down to the first window. The point is represented in the logical display space. The
3967 // point is selected so that if the hit test was done in logical display space, then it would
3968 // end up in the incorrect window.
3969 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3970 PointF{75 * 2, 55 * 4});
3971
3972 firstWindow->consumeMotionDown();
3973 secondWindow->assertNoEvents();
3974}
3975
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003976// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3977// event should be treated as being in the logical display space.
3978TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3979 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3980
3981 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3982 ui::Transform injectedEventTransform;
3983 injectedEventTransform.set(matrix);
3984 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3985 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3986
3987 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3988 .displayId(ADISPLAY_ID_DEFAULT)
3989 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00003990 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003991 .x(untransformedPoint.x)
3992 .y(untransformedPoint.y))
3993 .build();
3994 event.transform(matrix);
3995
3996 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
3997 InputEventInjectionSync::WAIT_FOR_RESULT);
3998
3999 firstWindow->consumeMotionDown();
4000 secondWindow->assertNoEvents();
4001}
4002
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004003TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4004 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4005
4006 // Send down to the second window.
4007 NotifyMotionArgs downMotionArgs =
4008 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4009 ADISPLAY_ID_DEFAULT, {PointF{150, 220}});
4010 mDispatcher->notifyMotion(&downMotionArgs);
4011
4012 firstWindow->assertNoEvents();
4013 const MotionEvent* event = secondWindow->consumeMotion();
4014 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4015
4016 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4017 EXPECT_EQ(300, event->getRawX(0));
4018 EXPECT_EQ(880, event->getRawY(0));
4019
4020 // Ensure that the x and y values are in the window's coordinate space.
4021 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4022 // the logical display space. This will be the origin of the window space.
4023 EXPECT_EQ(100, event->getX(0));
4024 EXPECT_EQ(80, event->getY(0));
4025}
4026
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004027using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4028 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004029
4030class TransferTouchFixture : public InputDispatcherTest,
4031 public ::testing::WithParamInterface<TransferFunction> {};
4032
4033TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004035
4036 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004037 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004038 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4039 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004040 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004041 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004042 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4043 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004044 sp<FakeWindowHandle> wallpaper =
4045 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4046 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004047 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004049
4050 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004051 NotifyMotionArgs downMotionArgs =
4052 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4053 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004054 mDispatcher->notifyMotion(&downMotionArgs);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004055
Svet Ganov5d3bc372020-01-26 23:11:07 -08004056 // Only the first window should get the down event
4057 firstWindow->consumeMotionDown();
4058 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004059 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004060
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004061 // Transfer touch to the second window
4062 TransferFunction f = GetParam();
4063 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4064 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004065 // The first window gets cancel and the second gets down
4066 firstWindow->consumeMotionCancel();
4067 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004068 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004069
4070 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004071 NotifyMotionArgs upMotionArgs =
4072 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4073 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004074 mDispatcher->notifyMotion(&upMotionArgs);
4075 // The first window gets no events and the second gets up
4076 firstWindow->assertNoEvents();
4077 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004078 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004079}
4080
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004081/**
4082 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4083 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4084 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4085 * natural to the user.
4086 * In this test, we are sending a pointer to both spy window and first window. We then try to
4087 * transfer touch to the second window. The dispatcher should identify the first window as the
4088 * one that should lose the gesture, and therefore the action should be to move the gesture from
4089 * the first window to the second.
4090 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4091 * the other API, as well.
4092 */
4093TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4095
4096 // Create a couple of windows + a spy window
4097 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004098 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004099 spyWindow->setTrustedOverlay(true);
4100 spyWindow->setSpy(true);
4101 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004102 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004103 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004104 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004105
4106 // Add the windows to the dispatcher
4107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4108
4109 // Send down to the first window
4110 NotifyMotionArgs downMotionArgs =
4111 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4112 ADISPLAY_ID_DEFAULT);
4113 mDispatcher->notifyMotion(&downMotionArgs);
4114 // Only the first window and spy should get the down event
4115 spyWindow->consumeMotionDown();
4116 firstWindow->consumeMotionDown();
4117
4118 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4119 // if f === 'transferTouch'.
4120 TransferFunction f = GetParam();
4121 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4122 ASSERT_TRUE(success);
4123 // The first window gets cancel and the second gets down
4124 firstWindow->consumeMotionCancel();
4125 secondWindow->consumeMotionDown();
4126
4127 // Send up event to the second window
4128 NotifyMotionArgs upMotionArgs =
4129 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4130 ADISPLAY_ID_DEFAULT);
4131 mDispatcher->notifyMotion(&upMotionArgs);
4132 // The first window gets no events and the second+spy get up
4133 firstWindow->assertNoEvents();
4134 spyWindow->consumeMotionUp();
4135 secondWindow->consumeMotionUp();
4136}
4137
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004138TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004140
4141 PointF touchPoint = {10, 10};
4142
4143 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004144 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004145 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4146 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004147 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004148 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004149 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4150 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004151 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004152
4153 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004155
4156 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004157 NotifyMotionArgs downMotionArgs =
4158 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4159 ADISPLAY_ID_DEFAULT, {touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004160 mDispatcher->notifyMotion(&downMotionArgs);
4161 // Only the first window should get the down event
4162 firstWindow->consumeMotionDown();
4163 secondWindow->assertNoEvents();
4164
4165 // Send pointer down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004166 NotifyMotionArgs pointerDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004167 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004168 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004169 mDispatcher->notifyMotion(&pointerDownMotionArgs);
4170 // Only the first window should get the pointer down event
4171 firstWindow->consumeMotionPointerDown(1);
4172 secondWindow->assertNoEvents();
4173
4174 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004175 TransferFunction f = GetParam();
4176 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4177 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004178 // The first window gets cancel and the second gets down and pointer down
4179 firstWindow->consumeMotionCancel();
4180 secondWindow->consumeMotionDown();
4181 secondWindow->consumeMotionPointerDown(1);
4182
4183 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004184 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004185 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004186 {touchPoint, touchPoint});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004187 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4188 // The first window gets nothing and the second gets pointer up
4189 firstWindow->assertNoEvents();
4190 secondWindow->consumeMotionPointerUp(1);
4191
4192 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004193 NotifyMotionArgs upMotionArgs =
4194 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4195 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004196 mDispatcher->notifyMotion(&upMotionArgs);
4197 // The first window gets nothing and the second gets up
4198 firstWindow->assertNoEvents();
4199 secondWindow->consumeMotionUp();
4200}
4201
Arthur Hungc539dbb2022-12-08 07:45:36 +00004202TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4204
4205 // Create a couple of windows
4206 sp<FakeWindowHandle> firstWindow =
4207 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4208 ADISPLAY_ID_DEFAULT);
4209 firstWindow->setDupTouchToWallpaper(true);
4210 sp<FakeWindowHandle> secondWindow =
4211 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4212 ADISPLAY_ID_DEFAULT);
4213 secondWindow->setDupTouchToWallpaper(true);
4214
4215 sp<FakeWindowHandle> wallpaper1 =
4216 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4217 wallpaper1->setIsWallpaper(true);
4218
4219 sp<FakeWindowHandle> wallpaper2 =
4220 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4221 wallpaper2->setIsWallpaper(true);
4222 // Add the windows to the dispatcher
4223 mDispatcher->setInputWindows(
4224 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4225
4226 // Send down to the first window
4227 NotifyMotionArgs downMotionArgs =
4228 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4229 ADISPLAY_ID_DEFAULT);
4230 mDispatcher->notifyMotion(&downMotionArgs);
4231
4232 // Only the first window should get the down event
4233 firstWindow->consumeMotionDown();
4234 secondWindow->assertNoEvents();
4235 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4236 wallpaper2->assertNoEvents();
4237
4238 // Transfer touch focus to the second window
4239 TransferFunction f = GetParam();
4240 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4241 ASSERT_TRUE(success);
4242
4243 // The first window gets cancel and the second gets down
4244 firstWindow->consumeMotionCancel();
4245 secondWindow->consumeMotionDown();
4246 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4247 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4248
4249 // Send up event to the second window
4250 NotifyMotionArgs upMotionArgs =
4251 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4252 ADISPLAY_ID_DEFAULT);
4253 mDispatcher->notifyMotion(&upMotionArgs);
4254 // The first window gets no events and the second gets up
4255 firstWindow->assertNoEvents();
4256 secondWindow->consumeMotionUp();
4257 wallpaper1->assertNoEvents();
4258 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4259}
4260
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004261// For the cases of single pointer touch and two pointers non-split touch, the api's
4262// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4263// for the case where there are multiple pointers split across several windows.
4264INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4265 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004266 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4267 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004268 return dispatcher->transferTouch(destChannelToken,
4269 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004270 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004271 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4272 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004273 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004274 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004275 }));
4276
Svet Ganov5d3bc372020-01-26 23:11:07 -08004277TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004279
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004280 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004281 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4282 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004283 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004284
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004285 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004286 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4287 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004288 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004289
4290 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004292
4293 PointF pointInFirst = {300, 200};
4294 PointF pointInSecond = {300, 600};
4295
4296 // Send down to the first window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004297 NotifyMotionArgs firstDownMotionArgs =
4298 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4299 ADISPLAY_ID_DEFAULT, {pointInFirst});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004300 mDispatcher->notifyMotion(&firstDownMotionArgs);
4301 // Only the first window should get the down event
4302 firstWindow->consumeMotionDown();
4303 secondWindow->assertNoEvents();
4304
4305 // Send down to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004306 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004307 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004308 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004309 mDispatcher->notifyMotion(&secondDownMotionArgs);
4310 // The first window gets a move and the second a down
4311 firstWindow->consumeMotionMove();
4312 secondWindow->consumeMotionDown();
4313
4314 // Transfer touch focus to the second window
4315 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4316 // The first window gets cancel and the new gets pointer down (it already saw down)
4317 firstWindow->consumeMotionCancel();
4318 secondWindow->consumeMotionPointerDown(1);
4319
4320 // Send pointer up to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004321 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004322 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004323 {pointInFirst, pointInSecond});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004324 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4325 // The first window gets nothing and the second gets pointer up
4326 firstWindow->assertNoEvents();
4327 secondWindow->consumeMotionPointerUp(1);
4328
4329 // Send up event to the second window
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004330 NotifyMotionArgs upMotionArgs =
4331 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4332 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004333 mDispatcher->notifyMotion(&upMotionArgs);
4334 // The first window gets nothing and the second gets up
4335 firstWindow->assertNoEvents();
4336 secondWindow->consumeMotionUp();
4337}
4338
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004339// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4340// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4341// touch is not supported, so the touch should continue on those windows and the transferred-to
4342// window should get nothing.
4343TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4344 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4345
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004346 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004347 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4348 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004349 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004350
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004351 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004352 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4353 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004354 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004355
4356 // Add the windows to the dispatcher
4357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4358
4359 PointF pointInFirst = {300, 200};
4360 PointF pointInSecond = {300, 600};
4361
4362 // Send down to the first window
4363 NotifyMotionArgs firstDownMotionArgs =
4364 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4365 ADISPLAY_ID_DEFAULT, {pointInFirst});
4366 mDispatcher->notifyMotion(&firstDownMotionArgs);
4367 // Only the first window should get the down event
4368 firstWindow->consumeMotionDown();
4369 secondWindow->assertNoEvents();
4370
4371 // Send down to the second window
4372 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004373 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004374 {pointInFirst, pointInSecond});
4375 mDispatcher->notifyMotion(&secondDownMotionArgs);
4376 // The first window gets a move and the second a down
4377 firstWindow->consumeMotionMove();
4378 secondWindow->consumeMotionDown();
4379
4380 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004381 const bool transferred =
4382 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004383 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4384 ASSERT_FALSE(transferred);
4385 firstWindow->assertNoEvents();
4386 secondWindow->assertNoEvents();
4387
4388 // The rest of the dispatch should proceed as normal
4389 // Send pointer up to the second window
4390 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004391 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004392 {pointInFirst, pointInSecond});
4393 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4394 // The first window gets MOVE and the second gets pointer up
4395 firstWindow->consumeMotionMove();
4396 secondWindow->consumeMotionUp();
4397
4398 // Send up event to the first window
4399 NotifyMotionArgs upMotionArgs =
4400 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4401 ADISPLAY_ID_DEFAULT);
4402 mDispatcher->notifyMotion(&upMotionArgs);
4403 // The first window gets nothing and the second gets up
4404 firstWindow->consumeMotionUp();
4405 secondWindow->assertNoEvents();
4406}
4407
Arthur Hungabbb9d82021-09-01 14:52:30 +00004408// This case will create two windows and one mirrored window on the default display and mirror
4409// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4410// the windows info of second display before default display.
4411TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4413 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004414 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004415 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004416 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004417 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004418 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004419
4420 sp<FakeWindowHandle> mirrorWindowInPrimary =
4421 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4422 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004423
4424 sp<FakeWindowHandle> firstWindowInSecondary =
4425 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4426 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004427
4428 sp<FakeWindowHandle> secondWindowInSecondary =
4429 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4430 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004431
4432 // Update window info, let it find window handle of second display first.
4433 mDispatcher->setInputWindows(
4434 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4435 {ADISPLAY_ID_DEFAULT,
4436 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4437
4438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4439 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4440 {50, 50}))
4441 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4442
4443 // Window should receive motion event.
4444 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4445
4446 // Transfer touch focus
4447 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4448 secondWindowInPrimary->getToken()));
4449 // The first window gets cancel.
4450 firstWindowInPrimary->consumeMotionCancel();
4451 secondWindowInPrimary->consumeMotionDown();
4452
4453 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4454 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4455 ADISPLAY_ID_DEFAULT, {150, 50}))
4456 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4457 firstWindowInPrimary->assertNoEvents();
4458 secondWindowInPrimary->consumeMotionMove();
4459
4460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4461 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4462 {150, 50}))
4463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4464 firstWindowInPrimary->assertNoEvents();
4465 secondWindowInPrimary->consumeMotionUp();
4466}
4467
4468// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4469// 'transferTouch' api.
4470TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4472 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004473 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004474 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004475 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004476 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004477 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004478
4479 sp<FakeWindowHandle> mirrorWindowInPrimary =
4480 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4481 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004482
4483 sp<FakeWindowHandle> firstWindowInSecondary =
4484 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4485 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004486
4487 sp<FakeWindowHandle> secondWindowInSecondary =
4488 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4489 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004490
4491 // Update window info, let it find window handle of second display first.
4492 mDispatcher->setInputWindows(
4493 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4494 {ADISPLAY_ID_DEFAULT,
4495 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4496
4497 // Touch on second display.
4498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4499 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4501
4502 // Window should receive motion event.
4503 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4504
4505 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004506 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004507
4508 // The first window gets cancel.
4509 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4510 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4511
4512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4513 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4514 SECOND_DISPLAY_ID, {150, 50}))
4515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4516 firstWindowInPrimary->assertNoEvents();
4517 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4518
4519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4520 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4522 firstWindowInPrimary->assertNoEvents();
4523 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4524}
4525
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004526TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004528 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4529 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004530
Vishnu Nair47074b82020-08-14 11:54:47 -07004531 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004532 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004533 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004534
4535 window->consumeFocusEvent(true);
4536
4537 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4538 mDispatcher->notifyKey(&keyArgs);
4539
4540 // Window should receive key down event.
4541 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4542}
4543
4544TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004545 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004546 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4547 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004548
Arthur Hung72d8dc32020-03-28 00:48:39 +00004549 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004550
4551 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4552 mDispatcher->notifyKey(&keyArgs);
4553 mDispatcher->waitForIdle();
4554
4555 window->assertNoEvents();
4556}
4557
4558// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4559TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004561 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4562 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004563
Arthur Hung72d8dc32020-03-28 00:48:39 +00004564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004565
4566 // Send key
4567 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4568 mDispatcher->notifyKey(&keyArgs);
4569 // Send motion
4570 NotifyMotionArgs motionArgs =
4571 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4572 ADISPLAY_ID_DEFAULT);
4573 mDispatcher->notifyMotion(&motionArgs);
4574
4575 // Window should receive only the motion event
4576 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4577 window->assertNoEvents(); // Key event or focus event will not be received
4578}
4579
arthurhungea3f4fc2020-12-21 23:18:53 +08004580TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4582
arthurhungea3f4fc2020-12-21 23:18:53 +08004583 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004584 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4585 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004586 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004587
arthurhungea3f4fc2020-12-21 23:18:53 +08004588 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004589 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4590 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004591 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004592
4593 // Add the windows to the dispatcher
4594 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4595
4596 PointF pointInFirst = {300, 200};
4597 PointF pointInSecond = {300, 600};
4598
4599 // Send down to the first window
4600 NotifyMotionArgs firstDownMotionArgs =
4601 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4602 ADISPLAY_ID_DEFAULT, {pointInFirst});
4603 mDispatcher->notifyMotion(&firstDownMotionArgs);
4604 // Only the first window should get the down event
4605 firstWindow->consumeMotionDown();
4606 secondWindow->assertNoEvents();
4607
4608 // Send down to the second window
4609 NotifyMotionArgs secondDownMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004610 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004611 {pointInFirst, pointInSecond});
4612 mDispatcher->notifyMotion(&secondDownMotionArgs);
4613 // The first window gets a move and the second a down
4614 firstWindow->consumeMotionMove();
4615 secondWindow->consumeMotionDown();
4616
4617 // Send pointer cancel to the second window
4618 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004619 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004620 {pointInFirst, pointInSecond});
4621 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
4622 mDispatcher->notifyMotion(&pointerUpMotionArgs);
4623 // The first window gets move and the second gets cancel.
4624 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4625 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4626
4627 // Send up event.
4628 NotifyMotionArgs upMotionArgs =
4629 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4630 ADISPLAY_ID_DEFAULT);
4631 mDispatcher->notifyMotion(&upMotionArgs);
4632 // The first window gets up and the second gets nothing.
4633 firstWindow->consumeMotionUp();
4634 secondWindow->assertNoEvents();
4635}
4636
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004637TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4639
4640 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004641 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4643 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4644 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4645 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4646
Harry Cutts33476232023-01-30 19:57:29 +00004647 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004648 window->assertNoEvents();
4649 mDispatcher->waitForIdle();
4650}
4651
chaviwd1c23182019-12-20 18:44:56 -08004652class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004653public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004654 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004655 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004656 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004657 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004658 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004659 }
4660
chaviwd1c23182019-12-20 18:44:56 -08004661 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4662
4663 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4664 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN,
4665 expectedDisplayId, expectedFlags);
4666 }
4667
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004668 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4669
4670 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4671
chaviwd1c23182019-12-20 18:44:56 -08004672 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4673 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
4674 expectedDisplayId, expectedFlags);
4675 }
4676
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004677 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4678 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE,
4679 expectedDisplayId, expectedFlags);
4680 }
4681
chaviwd1c23182019-12-20 18:44:56 -08004682 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
4683 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_UP,
4684 expectedDisplayId, expectedFlags);
4685 }
4686
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004687 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004688 mInputReceiver->consumeMotionEvent(
4689 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4690 WithDisplayId(expectedDisplayId),
4691 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004692 }
4693
Arthur Hungfbfa5722021-11-16 02:45:54 +00004694 void consumeMotionPointerDown(int32_t pointerIdx) {
4695 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4696 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
4697 mInputReceiver->consumeEvent(AINPUT_EVENT_TYPE_MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004698 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004699 }
4700
Evan Rosky84f07f02021-04-16 10:42:42 -07004701 MotionEvent* consumeMotion() {
4702 InputEvent* event = mInputReceiver->consume();
4703 if (!event) {
4704 ADD_FAILURE() << "No event was produced";
4705 return nullptr;
4706 }
4707 if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
4708 ADD_FAILURE() << "Received event of type " << event->getType() << " instead of motion";
4709 return nullptr;
4710 }
4711 return static_cast<MotionEvent*>(event);
4712 }
4713
chaviwd1c23182019-12-20 18:44:56 -08004714 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4715
4716private:
4717 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004718};
4719
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004720using InputDispatcherMonitorTest = InputDispatcherTest;
4721
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004722/**
4723 * Two entities that receive touch: A window, and a global monitor.
4724 * The touch goes to the window, and then the window disappears.
4725 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4726 * for the monitor, as well.
4727 * 1. foregroundWindow
4728 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4729 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004730TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4732 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004733 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004734
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004735 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004736
4737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4739 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4740 {100, 200}))
4741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4742
4743 // Both the foreground window and the global monitor should receive the touch down
4744 window->consumeMotionDown();
4745 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4746
4747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4748 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4749 ADISPLAY_ID_DEFAULT, {110, 200}))
4750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4751
4752 window->consumeMotionMove();
4753 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4754
4755 // Now the foreground window goes away
4756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4757 window->consumeMotionCancel();
4758 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4759
4760 // If more events come in, there will be no more foreground window to send them to. This will
4761 // cause a cancel for the monitor, as well.
4762 ASSERT_EQ(InputEventInjectionResult::FAILED,
4763 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4764 ADISPLAY_ID_DEFAULT, {120, 200}))
4765 << "Injection should fail because the window was removed";
4766 window->assertNoEvents();
4767 // Global monitor now gets the cancel
4768 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4769}
4770
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004771TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004773 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4774 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004775 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004776
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004777 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004778
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004780 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004782 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004783 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004784}
4785
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004786TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4787 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004788
Chris Yea209fde2020-07-22 13:54:51 -07004789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004790 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4791 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004792 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004793
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004795 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004797 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004798 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004799
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004800 // Pilfer pointers from the monitor.
4801 // This should not do anything and the window should continue to receive events.
4802 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004803
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004805 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4806 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004807 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004808
4809 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4810 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004811}
4812
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004813TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004815 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4816 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4818 window->setWindowOffset(20, 40);
4819 window->setWindowTransform(0, 1, -1, 0);
4820
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004821 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004822
4823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4824 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4826 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4827 MotionEvent* event = monitor.consumeMotion();
4828 // Even though window has transform, gesture monitor must not.
4829 ASSERT_EQ(ui::Transform(), event->getTransform());
4830}
4831
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004832TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004834 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004835
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004837 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004838 << "Injection should fail if there is a monitor, but no touchable window";
4839 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004840}
4841
chaviw81e2bb92019-12-18 15:03:51 -08004842TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004844 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4845 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004846
Arthur Hung72d8dc32020-03-28 00:48:39 +00004847 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004848
4849 NotifyMotionArgs motionArgs =
4850 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4851 ADISPLAY_ID_DEFAULT);
4852
4853 mDispatcher->notifyMotion(&motionArgs);
4854 // Window should receive motion down event.
4855 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4856
4857 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004858 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004859 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4860 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4861 motionArgs.pointerCoords[0].getX() - 10);
4862
4863 mDispatcher->notifyMotion(&motionArgs);
4864 window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004865 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004866}
4867
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004868/**
4869 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
4870 * the device default right away. In the test scenario, we check both the default value,
4871 * and the action of enabling / disabling.
4872 */
4873TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07004874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004875 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4876 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08004877 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004878
4879 // Set focused application.
4880 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004881 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004882
4883 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00004884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004885 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004886 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004887
4888 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004889 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004890 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004891 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004892
4893 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004894 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004895 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004896 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07004897 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004899 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004900 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004901
4902 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07004903 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004904 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00004905 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004906
4907 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08004908 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00004909 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00004910 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07004911 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004912 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004913 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004914 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004915
4916 window->assertNoEvents();
4917}
4918
Gang Wange9087892020-01-07 12:17:14 -05004919TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004921 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4922 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05004923
4924 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004925 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05004926
Arthur Hung72d8dc32020-03-28 00:48:39 +00004927 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004928 setFocusedWindow(window);
4929
Harry Cutts33476232023-01-30 19:57:29 +00004930 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05004931
4932 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
4933 mDispatcher->notifyKey(&keyArgs);
4934
4935 InputEvent* event = window->consume();
4936 ASSERT_NE(event, nullptr);
4937
4938 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4939 ASSERT_NE(verified, nullptr);
4940 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
4941
4942 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
4943 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
4944 ASSERT_EQ(keyArgs.source, verified->source);
4945 ASSERT_EQ(keyArgs.displayId, verified->displayId);
4946
4947 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
4948
4949 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05004950 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08004951 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05004952 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
4953 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
4954 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
4955 ASSERT_EQ(0, verifiedKey.repeatCount);
4956}
4957
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004958TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004960 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4961 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004962
4963 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4964
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004965 ui::Transform transform;
4966 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
4967
4968 gui::DisplayInfo displayInfo;
4969 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
4970 displayInfo.transform = transform;
4971
4972 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004973
4974 NotifyMotionArgs motionArgs =
4975 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4976 ADISPLAY_ID_DEFAULT);
4977 mDispatcher->notifyMotion(&motionArgs);
4978
4979 InputEvent* event = window->consume();
4980 ASSERT_NE(event, nullptr);
4981
4982 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
4983 ASSERT_NE(verified, nullptr);
4984 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
4985
4986 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
4987 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
4988 EXPECT_EQ(motionArgs.source, verified->source);
4989 EXPECT_EQ(motionArgs.displayId, verified->displayId);
4990
4991 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
4992
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07004993 const vec2 rawXY =
4994 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
4995 motionArgs.pointerCoords[0].getXYValue());
4996 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
4997 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004998 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08004999 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005000 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005001 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5002 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5003}
5004
chaviw09c8d2d2020-08-24 15:48:26 -07005005/**
5006 * Ensure that separate calls to sign the same data are generating the same key.
5007 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5008 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5009 * tests.
5010 */
5011TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5012 KeyEvent event = getTestKeyEvent();
5013 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5014
5015 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5016 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5017 ASSERT_EQ(hmac1, hmac2);
5018}
5019
5020/**
5021 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5022 */
5023TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5024 KeyEvent event = getTestKeyEvent();
5025 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5026 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5027
5028 verifiedEvent.deviceId += 1;
5029 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5030
5031 verifiedEvent.source += 1;
5032 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5033
5034 verifiedEvent.eventTimeNanos += 1;
5035 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5036
5037 verifiedEvent.displayId += 1;
5038 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5039
5040 verifiedEvent.action += 1;
5041 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5042
5043 verifiedEvent.downTimeNanos += 1;
5044 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5045
5046 verifiedEvent.flags += 1;
5047 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5048
5049 verifiedEvent.keyCode += 1;
5050 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5051
5052 verifiedEvent.scanCode += 1;
5053 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5054
5055 verifiedEvent.metaState += 1;
5056 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5057
5058 verifiedEvent.repeatCount += 1;
5059 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5060}
5061
Vishnu Nair958da932020-08-21 17:12:37 -07005062TEST_F(InputDispatcherTest, SetFocusedWindow) {
5063 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5064 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005065 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005066 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005067 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005068 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5069
5070 // Top window is also focusable but is not granted focus.
5071 windowTop->setFocusable(true);
5072 windowSecond->setFocusable(true);
5073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5074 setFocusedWindow(windowSecond);
5075
5076 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5078 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005079
5080 // Focused window should receive event.
5081 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5082 windowTop->assertNoEvents();
5083}
5084
5085TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5087 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005088 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005089 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5090
5091 window->setFocusable(true);
5092 // Release channel for window is no longer valid.
5093 window->releaseChannel();
5094 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5095 setFocusedWindow(window);
5096
5097 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005098 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5099 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005100
5101 // window channel is invalid, so it should not receive any input event.
5102 window->assertNoEvents();
5103}
5104
5105TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5107 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005108 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005109 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005110 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5111
Vishnu Nair958da932020-08-21 17:12:37 -07005112 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5113 setFocusedWindow(window);
5114
5115 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005116 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5117 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005118
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005119 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005120 window->assertNoEvents();
5121}
5122
5123TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5125 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005126 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005127 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005128 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005129 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5130
5131 windowTop->setFocusable(true);
5132 windowSecond->setFocusable(true);
5133 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5134 setFocusedWindow(windowTop);
5135 windowTop->consumeFocusEvent(true);
5136
5137 setFocusedWindow(windowSecond, windowTop);
5138 windowSecond->consumeFocusEvent(true);
5139 windowTop->consumeFocusEvent(false);
5140
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5142 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005143
5144 // Focused window should receive event.
5145 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5146}
5147
5148TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestFocusTokenNotFocused) {
5149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5150 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005151 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005152 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005153 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5155
5156 windowTop->setFocusable(true);
5157 windowSecond->setFocusable(true);
5158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5159 setFocusedWindow(windowSecond, windowTop);
5160
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005161 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5162 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005163
5164 // Event should be dropped.
5165 windowTop->assertNoEvents();
5166 windowSecond->assertNoEvents();
5167}
5168
5169TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
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 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005174 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5175 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005176 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5177
5178 window->setFocusable(true);
5179 previousFocusedWindow->setFocusable(true);
5180 window->setVisible(false);
5181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5182 setFocusedWindow(previousFocusedWindow);
5183 previousFocusedWindow->consumeFocusEvent(true);
5184
5185 // Requesting focus on invisible window takes focus from currently focused window.
5186 setFocusedWindow(window);
5187 previousFocusedWindow->consumeFocusEvent(false);
5188
5189 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005191 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5192 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005193
5194 // Window does not get focus event or key down.
5195 window->assertNoEvents();
5196
5197 // Window becomes visible.
5198 window->setVisible(true);
5199 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5200
5201 // Window receives focus event.
5202 window->consumeFocusEvent(true);
5203 // Focused window receives key down.
5204 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5205}
5206
Vishnu Nair599f1412021-06-21 10:39:58 -07005207TEST_F(InputDispatcherTest, DisplayRemoved) {
5208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5209 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005211 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5212
5213 // window is granted focus.
5214 window->setFocusable(true);
5215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5216 setFocusedWindow(window);
5217 window->consumeFocusEvent(true);
5218
5219 // When a display is removed window loses focus.
5220 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5221 window->consumeFocusEvent(false);
5222}
5223
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005224/**
5225 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5226 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5227 * of the 'slipperyEnterWindow'.
5228 *
5229 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5230 * a way so that the touched location is no longer covered by the top window.
5231 *
5232 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5233 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5234 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5235 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5236 * with ACTION_DOWN).
5237 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5238 * window moved itself away from the touched location and had Flag::SLIPPERY.
5239 *
5240 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5241 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5242 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5243 *
5244 * In this test, we ensure that the event received by the bottom window has
5245 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5246 */
5247TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005248 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5249 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005250
5251 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5252 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5253
5254 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005255 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005256 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005257 // Make sure this one overlaps the bottom window
5258 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5259 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5260 // one. Windows with the same owner are not considered to be occluding each other.
5261 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5262
5263 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005264 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005265 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5266
5267 mDispatcher->setInputWindows(
5268 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5269
5270 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
5271 NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5272 ADISPLAY_ID_DEFAULT, {{50, 50}});
5273 mDispatcher->notifyMotion(&args);
5274 slipperyExitWindow->consumeMotionDown();
5275 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5276 mDispatcher->setInputWindows(
5277 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5278
5279 args = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5280 ADISPLAY_ID_DEFAULT, {{51, 51}});
5281 mDispatcher->notifyMotion(&args);
5282
5283 slipperyExitWindow->consumeMotionCancel();
5284
5285 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5286 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5287}
5288
Garfield Tan1c7bc862020-01-28 13:24:04 -08005289class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5290protected:
5291 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5292 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5293
Chris Yea209fde2020-07-22 13:54:51 -07005294 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005295 sp<FakeWindowHandle> mWindow;
5296
5297 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005298 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005299 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005300 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005301 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5302 ASSERT_EQ(OK, mDispatcher->start());
5303
5304 setUpWindow();
5305 }
5306
5307 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005308 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005309 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005310
Vishnu Nair47074b82020-08-14 11:54:47 -07005311 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005313 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005314 mWindow->consumeFocusEvent(true);
5315 }
5316
Chris Ye2ad95392020-09-01 13:44:44 -07005317 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005318 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005319 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005320 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
5321 mDispatcher->notifyKey(&keyArgs);
5322
5323 // Window should receive key down event.
5324 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5325 }
5326
5327 void expectKeyRepeatOnce(int32_t repeatCount) {
5328 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5329 InputEvent* repeatEvent = mWindow->consume();
5330 ASSERT_NE(nullptr, repeatEvent);
5331
5332 uint32_t eventType = repeatEvent->getType();
5333 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
5334
5335 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5336 uint32_t eventAction = repeatKeyEvent->getAction();
5337 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5338 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5339 }
5340
Chris Ye2ad95392020-09-01 13:44:44 -07005341 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005342 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005343 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005344 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
5345 mDispatcher->notifyKey(&keyArgs);
5346
5347 // Window should receive key down event.
5348 mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005349 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005350 }
5351};
5352
5353TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005354 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005355 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5356 expectKeyRepeatOnce(repeatCount);
5357 }
5358}
5359
5360TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005361 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005362 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5363 expectKeyRepeatOnce(repeatCount);
5364 }
Harry Cutts33476232023-01-30 19:57:29 +00005365 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005366 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005367 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5368 expectKeyRepeatOnce(repeatCount);
5369 }
5370}
5371
5372TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005373 sendAndConsumeKeyDown(/*deviceId=*/1);
5374 expectKeyRepeatOnce(/*repeatCount=*/1);
5375 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005376 mWindow->assertNoEvents();
5377}
5378
5379TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005380 sendAndConsumeKeyDown(/*deviceId=*/1);
5381 expectKeyRepeatOnce(/*repeatCount=*/1);
5382 sendAndConsumeKeyDown(/*deviceId=*/2);
5383 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005384 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005385 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005386 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005387 expectKeyRepeatOnce(/*repeatCount=*/2);
5388 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005389 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005390 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005391 mWindow->assertNoEvents();
5392}
5393
5394TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005395 sendAndConsumeKeyDown(/*deviceId=*/1);
5396 expectKeyRepeatOnce(/*repeatCount=*/1);
5397 sendAndConsumeKeyDown(/*deviceId=*/2);
5398 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005399 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005400 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005401 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005402 mWindow->assertNoEvents();
5403}
5404
liushenxiang42232912021-05-21 20:24:09 +08005405TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5406 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005407 expectKeyRepeatOnce(/*repeatCount=*/1);
5408 NotifyDeviceResetArgs args(/*id=*/10, /*eventTime=*/20, DEVICE_ID);
liushenxiang42232912021-05-21 20:24:09 +08005409 mDispatcher->notifyDeviceReset(&args);
5410 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5411 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5412 mWindow->assertNoEvents();
5413}
5414
Garfield Tan1c7bc862020-01-28 13:24:04 -08005415TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Harry Cutts33476232023-01-30 19:57:29 +00005416 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005417 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5418 InputEvent* repeatEvent = mWindow->consume();
5419 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5420 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5421 IdGenerator::getSource(repeatEvent->getId()));
5422 }
5423}
5424
5425TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Harry Cutts33476232023-01-30 19:57:29 +00005426 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005427
5428 std::unordered_set<int32_t> idSet;
5429 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5430 InputEvent* repeatEvent = mWindow->consume();
5431 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5432 int32_t id = repeatEvent->getId();
5433 EXPECT_EQ(idSet.end(), idSet.find(id));
5434 idSet.insert(id);
5435 }
5436}
5437
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005438/* Test InputDispatcher for MultiDisplay */
5439class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5440public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005441 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005442 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005443
Chris Yea209fde2020-07-22 13:54:51 -07005444 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005445 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005446 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005447
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005448 // Set focus window for primary display, but focused display would be second one.
5449 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005450 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005451 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005452 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005453 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005454
Chris Yea209fde2020-07-22 13:54:51 -07005455 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005456 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005457 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005458 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005459 // Set focus display to second one.
5460 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5461 // Set focus window for second display.
5462 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005463 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005464 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005465 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005466 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005467 }
5468
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005469 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005470 InputDispatcherTest::TearDown();
5471
Chris Yea209fde2020-07-22 13:54:51 -07005472 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005473 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005474 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005475 windowInSecondary.clear();
5476 }
5477
5478protected:
Chris Yea209fde2020-07-22 13:54:51 -07005479 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005480 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005481 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005482 sp<FakeWindowHandle> windowInSecondary;
5483};
5484
5485TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5486 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5488 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005490 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005491 windowInSecondary->assertNoEvents();
5492
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005493 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5495 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005497 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005498 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005499}
5500
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005501TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005502 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5504 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005505 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005506 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005507 windowInSecondary->assertNoEvents();
5508
5509 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005511 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005512 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005513 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005514
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005515 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005516 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005517
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005518 // Old focus should receive a cancel event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005519 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
5520 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005521
5522 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005523 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005524 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005525 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005526 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005527 windowInSecondary->assertNoEvents();
5528}
5529
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005530// Test per-display input monitors for motion event.
5531TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005532 FakeMonitorReceiver monitorInPrimary =
5533 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5534 FakeMonitorReceiver monitorInSecondary =
5535 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005536
5537 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5539 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005541 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005542 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005543 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005544 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005545
5546 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5548 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005550 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005551 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005552 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005553 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005554
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005555 // Lift up the touch from the second display
5556 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5557 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5559 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5560 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5561
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005562 // Test inject a non-pointer motion event.
5563 // If specific a display, it will dispatch to the focused window of particular display,
5564 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005568 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005569 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005570 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005571 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005572}
5573
5574// Test per-display input monitors for key event.
5575TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005576 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005577 FakeMonitorReceiver monitorInPrimary =
5578 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5579 FakeMonitorReceiver monitorInSecondary =
5580 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005581
5582 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5584 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005585 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005586 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005587 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005588 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005589}
5590
Vishnu Nair958da932020-08-21 17:12:37 -07005591TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5592 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005593 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005594 secondWindowInPrimary->setFocusable(true);
5595 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5596 setFocusedWindow(secondWindowInPrimary);
5597 windowInPrimary->consumeFocusEvent(false);
5598 secondWindowInPrimary->consumeFocusEvent(true);
5599
5600 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5602 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005603 windowInPrimary->assertNoEvents();
5604 windowInSecondary->assertNoEvents();
5605 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5606}
5607
Arthur Hungdfd528e2021-12-08 13:23:04 +00005608TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5609 FakeMonitorReceiver monitorInPrimary =
5610 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5611 FakeMonitorReceiver monitorInSecondary =
5612 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5613
5614 // Test touch down on primary display.
5615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5616 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5618 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5619 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5620
5621 // Test touch down on second display.
5622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5623 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5625 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5626 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5627
5628 // Trigger cancel touch.
5629 mDispatcher->cancelCurrentTouch();
5630 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5631 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5632 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5633 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5634
5635 // Test inject a move motion event, no window/monitor should receive the event.
5636 ASSERT_EQ(InputEventInjectionResult::FAILED,
5637 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5638 ADISPLAY_ID_DEFAULT, {110, 200}))
5639 << "Inject motion event should return InputEventInjectionResult::FAILED";
5640 windowInPrimary->assertNoEvents();
5641 monitorInPrimary.assertNoEvents();
5642
5643 ASSERT_EQ(InputEventInjectionResult::FAILED,
5644 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5645 SECOND_DISPLAY_ID, {110, 200}))
5646 << "Inject motion event should return InputEventInjectionResult::FAILED";
5647 windowInSecondary->assertNoEvents();
5648 monitorInSecondary.assertNoEvents();
5649}
5650
Jackal Guof9696682018-10-05 12:23:23 +08005651class InputFilterTest : public InputDispatcherTest {
5652protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005653 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5654 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005655 NotifyMotionArgs motionArgs;
5656
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005657 motionArgs =
5658 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005659 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005660 motionArgs =
5661 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Jackal Guof9696682018-10-05 12:23:23 +08005662 mDispatcher->notifyMotion(&motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005663 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005664 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005665 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5666 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005667 } else {
5668 mFakePolicy->assertFilterInputEventWasNotCalled();
5669 }
5670 }
5671
5672 void testNotifyKey(bool expectToBeFiltered) {
5673 NotifyKeyArgs keyArgs;
5674
5675 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5676 mDispatcher->notifyKey(&keyArgs);
5677 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
5678 mDispatcher->notifyKey(&keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005679 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005680
5681 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005682 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005683 } else {
5684 mFakePolicy->assertFilterInputEventWasNotCalled();
5685 }
5686 }
5687};
5688
5689// Test InputFilter for MotionEvent
5690TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5691 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5692 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5693 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5694
5695 // Enable InputFilter
5696 mDispatcher->setInputFilterEnabled(true);
5697 // Test touch on both primary and second display, and check if both events are filtered.
5698 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5699 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5700
5701 // Disable InputFilter
5702 mDispatcher->setInputFilterEnabled(false);
5703 // Test touch on both primary and second display, and check if both events aren't filtered.
5704 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5705 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5706}
5707
5708// Test InputFilter for KeyEvent
5709TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5710 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5711 testNotifyKey(/*expectToBeFiltered*/ false);
5712
5713 // Enable InputFilter
5714 mDispatcher->setInputFilterEnabled(true);
5715 // Send a key event, and check if it is filtered.
5716 testNotifyKey(/*expectToBeFiltered*/ true);
5717
5718 // Disable InputFilter
5719 mDispatcher->setInputFilterEnabled(false);
5720 // Send a key event, and check if it isn't filtered.
5721 testNotifyKey(/*expectToBeFiltered*/ false);
5722}
5723
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005724// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5725// logical display coordinate space.
5726TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5727 ui::Transform firstDisplayTransform;
5728 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5729 ui::Transform secondDisplayTransform;
5730 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5731
5732 std::vector<gui::DisplayInfo> displayInfos(2);
5733 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5734 displayInfos[0].transform = firstDisplayTransform;
5735 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5736 displayInfos[1].transform = secondDisplayTransform;
5737
5738 mDispatcher->onWindowInfosChanged({}, displayInfos);
5739
5740 // Enable InputFilter
5741 mDispatcher->setInputFilterEnabled(true);
5742
5743 // Ensure the correct transforms are used for the displays.
5744 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5745 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5746}
5747
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005748class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5749protected:
5750 virtual void SetUp() override {
5751 InputDispatcherTest::SetUp();
5752
5753 /**
5754 * We don't need to enable input filter to test the injected event policy, but we enabled it
5755 * here to make the tests more realistic, since this policy only matters when inputfilter is
5756 * on.
5757 */
5758 mDispatcher->setInputFilterEnabled(true);
5759
5760 std::shared_ptr<InputApplicationHandle> application =
5761 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005762 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5763 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005764
5765 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5766 mWindow->setFocusable(true);
5767 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5768 setFocusedWindow(mWindow);
5769 mWindow->consumeFocusEvent(true);
5770 }
5771
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005772 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5773 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005774 KeyEvent event;
5775
5776 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5777 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5778 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005779 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005780 const int32_t additionalPolicyFlags =
5781 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005784 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5785 policyFlags | additionalPolicyFlags));
5786
5787 InputEvent* received = mWindow->consume();
5788 ASSERT_NE(nullptr, received);
5789 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005790 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_KEY);
5791 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5792 ASSERT_EQ(flags, keyEvent.getFlags());
5793 }
5794
5795 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5796 int32_t flags) {
5797 MotionEvent event;
5798 PointerProperties pointerProperties[1];
5799 PointerCoords pointerCoords[1];
5800 pointerProperties[0].clear();
5801 pointerProperties[0].id = 0;
5802 pointerCoords[0].clear();
5803 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5804 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5805
5806 ui::Transform identityTransform;
5807 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5808 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5809 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5810 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5811 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005812 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005813 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005814 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5815
5816 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005818 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005819 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5820 policyFlags | additionalPolicyFlags));
5821
5822 InputEvent* received = mWindow->consume();
5823 ASSERT_NE(nullptr, received);
5824 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
5825 ASSERT_EQ(received->getType(), AINPUT_EVENT_TYPE_MOTION);
5826 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5827 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005828 }
5829
5830private:
5831 sp<FakeWindowHandle> mWindow;
5832};
5833
5834TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005835 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5836 // filter. Without it, the event will no different from a regularly injected event, and the
5837 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005838 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5839 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005840}
5841
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005842TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005843 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005844 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005845 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5846}
5847
5848TEST_F(InputFilterInjectionPolicyTest,
5849 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5850 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005851 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005852 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005853}
5854
5855TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005856 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5857 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005858}
5859
chaviwfd6d3512019-03-25 13:23:49 -07005860class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005861 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005862 InputDispatcherTest::SetUp();
5863
Chris Yea209fde2020-07-22 13:54:51 -07005864 std::shared_ptr<FakeApplicationHandle> application =
5865 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005866 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005867 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005868 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07005869
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005870 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005871 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005872 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07005873
5874 // Set focused application.
5875 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005876 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07005877
5878 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005879 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005880 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005881 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07005882 }
5883
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005884 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07005885 InputDispatcherTest::TearDown();
5886
5887 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005888 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07005889 }
5890
5891protected:
5892 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005893 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005894 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07005895};
5896
5897// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5898// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
5899// the onPointerDownOutsideFocus callback.
5900TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005902 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5903 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005905 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005906
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005907 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07005908 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
5909}
5910
5911// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
5912// DOWN on the window that doesn't have focus. Ensure no window received the
5913// onPointerDownOutsideFocus callback.
5914TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005915 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005916 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005918 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005919
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005920 ASSERT_TRUE(mDispatcher->waitForIdle());
5921 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005922}
5923
5924// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
5925// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
5926TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5928 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005929 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005930 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005931
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005932 ASSERT_TRUE(mDispatcher->waitForIdle());
5933 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005934}
5935
5936// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
5937// DOWN on the window that already has focus. Ensure no window received the
5938// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005939TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005941 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07005942 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07005944 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07005945
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005946 ASSERT_TRUE(mDispatcher->waitForIdle());
5947 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07005948}
5949
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005950// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
5951// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
5952TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
5953 const MotionEvent event =
5954 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5955 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00005956 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08005957 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
5958 .build();
5959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
5960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5961 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5962
5963 ASSERT_TRUE(mDispatcher->waitForIdle());
5964 mFakePolicy->assertOnPointerDownWasNotCalled();
5965 // Ensure that the unfocused window did not receive any FOCUS events.
5966 mUnfocusedWindow->assertNoEvents();
5967}
5968
chaviwaf87b3e2019-10-01 16:59:28 -07005969// These tests ensures we can send touch events to a single client when there are multiple input
5970// windows that point to the same client token.
5971class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
5972 virtual void SetUp() override {
5973 InputDispatcherTest::SetUp();
5974
Chris Yea209fde2020-07-22 13:54:51 -07005975 std::shared_ptr<FakeApplicationHandle> application =
5976 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005977 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
5978 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07005979 mWindow1->setFrame(Rect(0, 0, 100, 100));
5980
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005981 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
5982 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07005983 mWindow2->setFrame(Rect(100, 100, 200, 200));
5984
Arthur Hung72d8dc32020-03-28 00:48:39 +00005985 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07005986 }
5987
5988protected:
5989 sp<FakeWindowHandle> mWindow1;
5990 sp<FakeWindowHandle> mWindow2;
5991
5992 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05005993 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07005994 vec2 vals = windowInfo->transform.transform(point.x, point.y);
5995 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07005996 }
5997
5998 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
5999 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006000 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006001 InputEvent* event = window->consume();
6002
6003 ASSERT_NE(nullptr, event) << name.c_str()
6004 << ": consumer should have returned non-NULL event.";
6005
6006 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
6007 << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
6008 << " event, got " << inputEventTypeToString(event->getType()) << " event";
6009
6010 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006011 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006012 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006013
6014 for (size_t i = 0; i < points.size(); i++) {
6015 float expectedX = points[i].x;
6016 float expectedY = points[i].y;
6017
6018 EXPECT_EQ(expectedX, motionEvent.getX(i))
6019 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6020 << ", got " << motionEvent.getX(i);
6021 EXPECT_EQ(expectedY, motionEvent.getY(i))
6022 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6023 << ", got " << motionEvent.getY(i);
6024 }
6025 }
chaviw9eaa22c2020-07-01 16:21:27 -07006026
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006027 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006028 std::vector<PointF> expectedPoints) {
6029 NotifyMotionArgs motionArgs = generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6030 ADISPLAY_ID_DEFAULT, touchedPoints);
6031 mDispatcher->notifyMotion(&motionArgs);
6032
6033 // Always consume from window1 since it's the window that has the InputReceiver
6034 consumeMotionEvent(mWindow1, action, expectedPoints);
6035 }
chaviwaf87b3e2019-10-01 16:59:28 -07006036};
6037
6038TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6039 // Touch Window 1
6040 PointF touchedPoint = {10, 10};
6041 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006042 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006043
6044 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006045 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006046
6047 // Touch Window 2
6048 touchedPoint = {150, 150};
6049 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006050 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006051}
6052
chaviw9eaa22c2020-07-01 16:21:27 -07006053TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6054 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006055 mWindow2->setWindowScale(0.5f, 0.5f);
6056
6057 // Touch Window 1
6058 PointF touchedPoint = {10, 10};
6059 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006060 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006061 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006062 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006063
6064 // Touch Window 2
6065 touchedPoint = {150, 150};
6066 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006067 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6068 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006069
chaviw9eaa22c2020-07-01 16:21:27 -07006070 // Update the transform so rotation is set
6071 mWindow2->setWindowTransform(0, -1, 1, 0);
6072 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6073 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006074}
6075
chaviw9eaa22c2020-07-01 16:21:27 -07006076TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006077 mWindow2->setWindowScale(0.5f, 0.5f);
6078
6079 // Touch Window 1
6080 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6081 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006082 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006083
6084 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006085 touchedPoints.push_back(PointF{150, 150});
6086 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006087 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006088
chaviw9eaa22c2020-07-01 16:21:27 -07006089 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006090 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006091 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006092
chaviw9eaa22c2020-07-01 16:21:27 -07006093 // Update the transform so rotation is set for Window 2
6094 mWindow2->setWindowTransform(0, -1, 1, 0);
6095 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006096 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006097}
6098
chaviw9eaa22c2020-07-01 16:21:27 -07006099TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006100 mWindow2->setWindowScale(0.5f, 0.5f);
6101
6102 // Touch Window 1
6103 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6104 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006105 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006106
6107 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006108 touchedPoints.push_back(PointF{150, 150});
6109 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006110
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006111 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006112
6113 // Move both windows
6114 touchedPoints = {{20, 20}, {175, 175}};
6115 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6116 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6117
chaviw9eaa22c2020-07-01 16:21:27 -07006118 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006119
chaviw9eaa22c2020-07-01 16:21:27 -07006120 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006121 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006122 expectedPoints.pop_back();
6123
6124 // Touch Window 2
6125 mWindow2->setWindowTransform(0, -1, 1, 0);
6126 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006127 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006128
6129 // Move both windows
6130 touchedPoints = {{20, 20}, {175, 175}};
6131 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6132 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6133
6134 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006135}
6136
6137TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6138 mWindow1->setWindowScale(0.5f, 0.5f);
6139
6140 // Touch Window 1
6141 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6142 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006143 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006144
6145 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006146 touchedPoints.push_back(PointF{150, 150});
6147 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006148
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006149 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006150
6151 // Move both windows
6152 touchedPoints = {{20, 20}, {175, 175}};
6153 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6154 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6155
chaviw9eaa22c2020-07-01 16:21:27 -07006156 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006157}
6158
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006159class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6160 virtual void SetUp() override {
6161 InputDispatcherTest::SetUp();
6162
Chris Yea209fde2020-07-22 13:54:51 -07006163 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006164 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006165 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6166 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006167 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006168 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006169 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006170
6171 // Set focused application.
6172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6173
6174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006175 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006176 mWindow->consumeFocusEvent(true);
6177 }
6178
6179 virtual void TearDown() override {
6180 InputDispatcherTest::TearDown();
6181 mWindow.clear();
6182 }
6183
6184protected:
Chris Yea209fde2020-07-22 13:54:51 -07006185 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006186 sp<FakeWindowHandle> mWindow;
6187 static constexpr PointF WINDOW_LOCATION = {20, 20};
6188
6189 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006191 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6192 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006194 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6195 WINDOW_LOCATION));
6196 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006197
6198 sp<FakeWindowHandle> addSpyWindow() {
6199 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006200 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006201 spy->setTrustedOverlay(true);
6202 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006203 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006204 spy->setDispatchingTimeout(30ms);
6205 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6206 return spy;
6207 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006208};
6209
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006210// Send a tap and respond, which should not cause an ANR.
6211TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6212 tapOnWindow();
6213 mWindow->consumeMotionDown();
6214 mWindow->consumeMotionUp();
6215 ASSERT_TRUE(mDispatcher->waitForIdle());
6216 mFakePolicy->assertNotifyAnrWasNotCalled();
6217}
6218
6219// Send a regular key and respond, which should not cause an ANR.
6220TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006222 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6223 ASSERT_TRUE(mDispatcher->waitForIdle());
6224 mFakePolicy->assertNotifyAnrWasNotCalled();
6225}
6226
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006227TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6228 mWindow->setFocusable(false);
6229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6230 mWindow->consumeFocusEvent(false);
6231
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006232 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006233 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6234 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6235 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006237 // Key will not go to window because we have no focused window.
6238 // The 'no focused window' ANR timer should start instead.
6239
6240 // Now, the focused application goes away.
6241 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6242 // The key should get dropped and there should be no ANR.
6243
6244 ASSERT_TRUE(mDispatcher->waitForIdle());
6245 mFakePolicy->assertNotifyAnrWasNotCalled();
6246}
6247
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006248// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006249// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6250// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006251TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006253 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6254 WINDOW_LOCATION));
6255
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006256 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6257 ASSERT_TRUE(sequenceNum);
6258 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006259 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006260
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006261 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006262 mWindow->consumeMotionEvent(
6263 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006264 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006265 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006266}
6267
6268// Send a key to the app and have the app not respond right away.
6269TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6270 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006272 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6273 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006274 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006275 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006276 ASSERT_TRUE(mDispatcher->waitForIdle());
6277}
6278
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006279// We have a focused application, but no focused window
6280TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006281 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6283 mWindow->consumeFocusEvent(false);
6284
6285 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006287 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6288 WINDOW_LOCATION));
6289 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6290 mDispatcher->waitForIdle();
6291 mFakePolicy->assertNotifyAnrWasNotCalled();
6292
6293 // Once a focused event arrives, we get an ANR for this application
6294 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6295 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006296 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006297 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6298 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006299 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006300 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006301 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006302 ASSERT_TRUE(mDispatcher->waitForIdle());
6303}
6304
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006305/**
6306 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6307 * there will not be an ANR.
6308 */
6309TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6310 mWindow->setFocusable(false);
6311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6312 mWindow->consumeFocusEvent(false);
6313
6314 KeyEvent event;
6315 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6316 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6317
6318 // Define a valid key down event that is stale (too old).
6319 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6320 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006321 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006322
6323 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6324
6325 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006326 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006327 InputEventInjectionSync::WAIT_FOR_RESULT,
6328 INJECT_EVENT_TIMEOUT, policyFlags);
6329 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6330 << "Injection should fail because the event is stale";
6331
6332 ASSERT_TRUE(mDispatcher->waitForIdle());
6333 mFakePolicy->assertNotifyAnrWasNotCalled();
6334 mWindow->assertNoEvents();
6335}
6336
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006337// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006338// Make sure that we don't notify policy twice about the same ANR.
6339TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006340 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6342 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006343
6344 // Once a focused event arrives, we get an ANR for this application
6345 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6346 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006347 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006348 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6349 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006350 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006351 const std::chrono::duration appTimeout =
6352 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6353 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006354
Vishnu Naire4df8752022-09-08 09:17:55 -07006355 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006356 // ANR should not be raised again. It is up to policy to do that if it desires.
6357 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006358
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006359 // If we now get a focused window, the ANR should stop, but the policy handles that via
6360 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006361 ASSERT_TRUE(mDispatcher->waitForIdle());
6362}
6363
6364// We have a focused application, but no focused window
6365TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006366 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006367 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6368 mWindow->consumeFocusEvent(false);
6369
6370 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006371 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006372 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006373 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6374 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006375
Vishnu Naire4df8752022-09-08 09:17:55 -07006376 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6377 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006378
6379 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006380 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006381 ASSERT_TRUE(mDispatcher->waitForIdle());
6382 mWindow->assertNoEvents();
6383}
6384
6385/**
6386 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6387 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6388 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6389 * the ANR mechanism should still work.
6390 *
6391 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6392 * DOWN event, while not responding on the second one.
6393 */
6394TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6395 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6396 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6397 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6398 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6399 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006400 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006401
6402 // Now send ACTION_UP, with identical timestamp
6403 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6404 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6405 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6406 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006407 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006408
6409 // We have now sent down and up. Let's consume first event and then ANR on the second.
6410 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6411 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006412 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006413}
6414
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006415// A spy window can receive an ANR
6416TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6417 sp<FakeWindowHandle> spy = addSpyWindow();
6418
6419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6420 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6421 WINDOW_LOCATION));
6422 mWindow->consumeMotionDown();
6423
6424 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6425 ASSERT_TRUE(sequenceNum);
6426 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006427 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006428
6429 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006430 spy->consumeMotionEvent(
6431 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006432 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006433 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006434}
6435
6436// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006437// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006438TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6439 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006440
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6442 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006443 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006445
6446 // Stuck on the ACTION_UP
6447 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006448 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006449
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006450 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006451 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006452 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6453 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006454
6455 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6456 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006457 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006458 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006459 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006460}
6461
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006462// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006463// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006464TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6465 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006466
6467 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006468 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6469 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006470
6471 mWindow->consumeMotionDown();
6472 // Stuck on the ACTION_UP
6473 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006474 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006475
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006476 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006477 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006478 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6479 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006480
6481 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6482 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006483 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006484 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006485 spy->assertNoEvents();
6486}
6487
6488TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6489 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6490
6491 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6492
6493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6494 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6495 WINDOW_LOCATION));
6496
6497 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6498 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6499 ASSERT_TRUE(consumeSeq);
6500
Prabir Pradhanedd96402022-02-15 01:46:16 -08006501 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006502
6503 monitor.finishEvent(*consumeSeq);
6504 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6505
6506 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006507 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006508}
6509
6510// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6511// process events, you don't get an anr. When the window later becomes unresponsive again, you
6512// get an ANR again.
6513// 1. tap -> block on ACTION_UP -> receive ANR
6514// 2. consume all pending events (= queue becomes healthy again)
6515// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6516TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6517 tapOnWindow();
6518
6519 mWindow->consumeMotionDown();
6520 // Block on ACTION_UP
6521 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006522 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006523 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6524 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006525 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006526 mWindow->assertNoEvents();
6527
6528 tapOnWindow();
6529 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006530 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006531 mWindow->consumeMotionUp();
6532
6533 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006534 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006535 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006536 mWindow->assertNoEvents();
6537}
6538
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006539// If a connection remains unresponsive for a while, make sure policy is only notified once about
6540// it.
6541TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006543 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6544 WINDOW_LOCATION));
6545
6546 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006547 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006548 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006549 // 'notifyConnectionUnresponsive' should only be called once per connection
6550 mFakePolicy->assertNotifyAnrWasNotCalled();
6551 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006552 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006553 mWindow->consumeMotionEvent(
6554 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006555 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006556 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006557 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006558 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006559}
6560
6561/**
6562 * If a window is processing a motion event, and then a key event comes in, the key event should
6563 * not to to the focused window until the motion is processed.
6564 *
6565 * Warning!!!
6566 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6567 * and the injection timeout that we specify when injecting the key.
6568 * We must have the injection timeout (10ms) be smaller than
6569 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6570 *
6571 * If that value changes, this test should also change.
6572 */
6573TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6574 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6576
6577 tapOnWindow();
6578 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6579 ASSERT_TRUE(downSequenceNum);
6580 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6581 ASSERT_TRUE(upSequenceNum);
6582 // Don't finish the events yet, and send a key
6583 // Injection will "succeed" because we will eventually give up and send the key to the focused
6584 // window even if motions are still being processed. But because the injection timeout is short,
6585 // we will receive INJECTION_TIMED_OUT as the result.
6586
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006587 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006588 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006589 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6590 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006591 // Key will not be sent to the window, yet, because the window is still processing events
6592 // and the key remains pending, waiting for the touch events to be processed
6593 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6594 ASSERT_FALSE(keySequenceNum);
6595
6596 std::this_thread::sleep_for(500ms);
6597 // if we wait long enough though, dispatcher will give up, and still send the key
6598 // to the focused window, even though we have not yet finished the motion event
6599 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6600 mWindow->finishEvent(*downSequenceNum);
6601 mWindow->finishEvent(*upSequenceNum);
6602}
6603
6604/**
6605 * If a window is processing a motion event, and then a key event comes in, the key event should
6606 * not go to the focused window until the motion is processed.
6607 * If then a new motion comes in, then the pending key event should be going to the currently
6608 * focused window right away.
6609 */
6610TEST_F(InputDispatcherSingleWindowAnr,
6611 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6612 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6614
6615 tapOnWindow();
6616 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6617 ASSERT_TRUE(downSequenceNum);
6618 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6619 ASSERT_TRUE(upSequenceNum);
6620 // Don't finish the events yet, and send a key
6621 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006623 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6624 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006625 // At this point, key is still pending, and should not be sent to the application yet.
6626 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6627 ASSERT_FALSE(keySequenceNum);
6628
6629 // Now tap down again. It should cause the pending key to go to the focused window right away.
6630 tapOnWindow();
6631 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6632 // the other events yet. We can finish events in any order.
6633 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6634 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6635 mWindow->consumeMotionDown();
6636 mWindow->consumeMotionUp();
6637 mWindow->assertNoEvents();
6638}
6639
6640class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6641 virtual void SetUp() override {
6642 InputDispatcherTest::SetUp();
6643
Chris Yea209fde2020-07-22 13:54:51 -07006644 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006645 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006646 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6647 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006648 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006649 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006650 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006651
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006652 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6653 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006654 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006655 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006656
6657 // Set focused application.
6658 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006659 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006660
6661 // Expect one focus window exist in display.
6662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006663 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006664 mFocusedWindow->consumeFocusEvent(true);
6665 }
6666
6667 virtual void TearDown() override {
6668 InputDispatcherTest::TearDown();
6669
6670 mUnfocusedWindow.clear();
6671 mFocusedWindow.clear();
6672 }
6673
6674protected:
Chris Yea209fde2020-07-22 13:54:51 -07006675 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006676 sp<FakeWindowHandle> mUnfocusedWindow;
6677 sp<FakeWindowHandle> mFocusedWindow;
6678 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6679 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6680 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6681
6682 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6683
6684 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6685
6686private:
6687 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006689 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6690 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006692 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6693 location));
6694 }
6695};
6696
6697// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6698// should be ANR'd first.
6699TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006701 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6702 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006704 mFocusedWindow->consumeMotionDown();
6705 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006706 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006707 // We consumed all events, so no ANR
6708 ASSERT_TRUE(mDispatcher->waitForIdle());
6709 mFakePolicy->assertNotifyAnrWasNotCalled();
6710
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006712 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6713 FOCUSED_WINDOW_LOCATION));
6714 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6715 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006716
6717 const std::chrono::duration timeout =
6718 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006719 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006720 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6721 // sequence to make it consistent
6722 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006723 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006724 mFocusedWindow->consumeMotionDown();
6725 // This cancel is generated because the connection was unresponsive
6726 mFocusedWindow->consumeMotionCancel();
6727 mFocusedWindow->assertNoEvents();
6728 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006729 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006730 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6731 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006732 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006733}
6734
6735// If we have 2 windows with identical timeouts that are both unresponsive,
6736// it doesn't matter which order they should have ANR.
6737// But we should receive ANR for both.
6738TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6739 // Set the timeout for unfocused window to match the focused window
6740 mUnfocusedWindow->setDispatchingTimeout(10ms);
6741 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6742
6743 tapOnFocusedWindow();
6744 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006745 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6746 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6747 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006748
6749 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006750 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6751 mFocusedWindow->getToken() == anrConnectionToken2);
6752 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6753 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006754
6755 ASSERT_TRUE(mDispatcher->waitForIdle());
6756 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006757
6758 mFocusedWindow->consumeMotionDown();
6759 mFocusedWindow->consumeMotionUp();
6760 mUnfocusedWindow->consumeMotionOutside();
6761
Prabir Pradhanedd96402022-02-15 01:46:16 -08006762 sp<IBinder> responsiveToken1, responsiveToken2;
6763 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6764 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006765
6766 // Both applications should be marked as responsive, in any order
6767 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6768 mFocusedWindow->getToken() == responsiveToken2);
6769 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6770 mUnfocusedWindow->getToken() == responsiveToken2);
6771 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006772}
6773
6774// If a window is already not responding, the second tap on the same window should be ignored.
6775// We should also log an error to account for the dropped event (not tested here).
6776// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6777TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6778 tapOnFocusedWindow();
6779 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006780 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006781 // Receive the events, but don't respond
6782 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6783 ASSERT_TRUE(downEventSequenceNum);
6784 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6785 ASSERT_TRUE(upEventSequenceNum);
6786 const std::chrono::duration timeout =
6787 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006788 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789
6790 // Tap once again
6791 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006792 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6794 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006795 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006796 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6797 FOCUSED_WINDOW_LOCATION));
6798 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6799 // valid touch target
6800 mUnfocusedWindow->assertNoEvents();
6801
6802 // Consume the first tap
6803 mFocusedWindow->finishEvent(*downEventSequenceNum);
6804 mFocusedWindow->finishEvent(*upEventSequenceNum);
6805 ASSERT_TRUE(mDispatcher->waitForIdle());
6806 // The second tap did not go to the focused window
6807 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006808 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006809 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6810 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006811 mFakePolicy->assertNotifyAnrWasNotCalled();
6812}
6813
6814// If you tap outside of all windows, there will not be ANR
6815TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006816 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6818 LOCATION_OUTSIDE_ALL_WINDOWS));
6819 ASSERT_TRUE(mDispatcher->waitForIdle());
6820 mFakePolicy->assertNotifyAnrWasNotCalled();
6821}
6822
6823// Since the focused window is paused, tapping on it should not produce any events
6824TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6825 mFocusedWindow->setPaused(true);
6826 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6827
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006828 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006829 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6830 FOCUSED_WINDOW_LOCATION));
6831
6832 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6833 ASSERT_TRUE(mDispatcher->waitForIdle());
6834 // Should not ANR because the window is paused, and touches shouldn't go to it
6835 mFakePolicy->assertNotifyAnrWasNotCalled();
6836
6837 mFocusedWindow->assertNoEvents();
6838 mUnfocusedWindow->assertNoEvents();
6839}
6840
6841/**
6842 * If a window is processing a motion event, and then a key event comes in, the key event should
6843 * not to to the focused window until the motion is processed.
6844 * If a different window becomes focused at this time, the key should go to that window instead.
6845 *
6846 * Warning!!!
6847 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6848 * and the injection timeout that we specify when injecting the key.
6849 * We must have the injection timeout (10ms) be smaller than
6850 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6851 *
6852 * If that value changes, this test should also change.
6853 */
6854TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
6855 // Set a long ANR timeout to prevent it from triggering
6856 mFocusedWindow->setDispatchingTimeout(2s);
6857 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6858
6859 tapOnUnfocusedWindow();
6860 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
6861 ASSERT_TRUE(downSequenceNum);
6862 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
6863 ASSERT_TRUE(upSequenceNum);
6864 // Don't finish the events yet, and send a key
6865 // Injection will succeed because we will eventually give up and send the key to the focused
6866 // window even if motions are still being processed.
6867
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006868 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006869 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6870 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006872 // Key will not be sent to the window, yet, because the window is still processing events
6873 // and the key remains pending, waiting for the touch events to be processed
6874 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
6875 ASSERT_FALSE(keySequenceNum);
6876
6877 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07006878 mFocusedWindow->setFocusable(false);
6879 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006880 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006881 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006882
6883 // Focus events should precede the key events
6884 mUnfocusedWindow->consumeFocusEvent(true);
6885 mFocusedWindow->consumeFocusEvent(false);
6886
6887 // Finish the tap events, which should unblock dispatcher
6888 mUnfocusedWindow->finishEvent(*downSequenceNum);
6889 mUnfocusedWindow->finishEvent(*upSequenceNum);
6890
6891 // Now that all queues are cleared and no backlog in the connections, the key event
6892 // can finally go to the newly focused "mUnfocusedWindow".
6893 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6894 mFocusedWindow->assertNoEvents();
6895 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006896 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897}
6898
6899// When the touch stream is split across 2 windows, and one of them does not respond,
6900// then ANR should be raised and the touch should be canceled for the unresponsive window.
6901// The other window should not be affected by that.
6902TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
6903 // Touch Window 1
6904 NotifyMotionArgs motionArgs =
6905 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6906 ADISPLAY_ID_DEFAULT, {FOCUSED_WINDOW_LOCATION});
6907 mDispatcher->notifyMotion(&motionArgs);
6908 mUnfocusedWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006909 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006910
6911 // Touch Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006912 motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6913 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914 mDispatcher->notifyMotion(&motionArgs);
6915
6916 const std::chrono::duration timeout =
6917 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006918 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919
6920 mUnfocusedWindow->consumeMotionDown();
6921 mFocusedWindow->consumeMotionDown();
6922 // Focused window may or may not receive ACTION_MOVE
6923 // But it should definitely receive ACTION_CANCEL due to the ANR
6924 InputEvent* event;
6925 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
6926 ASSERT_TRUE(moveOrCancelSequenceNum);
6927 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
6928 ASSERT_NE(nullptr, event);
6929 ASSERT_EQ(event->getType(), AINPUT_EVENT_TYPE_MOTION);
6930 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
6931 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
6932 mFocusedWindow->consumeMotionCancel();
6933 } else {
6934 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
6935 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006936 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006937 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6938 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006939
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006940 mUnfocusedWindow->assertNoEvents();
6941 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006942 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006943}
6944
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006945/**
6946 * If we have no focused window, and a key comes in, we start the ANR timer.
6947 * The focused application should add a focused window before the timer runs out to prevent ANR.
6948 *
6949 * If the user touches another application during this time, the key should be dropped.
6950 * Next, if a new focused window comes in, without toggling the focused application,
6951 * then no ANR should occur.
6952 *
6953 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
6954 * but in some cases the policy may not update the focused application.
6955 */
6956TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
6957 std::shared_ptr<FakeApplicationHandle> focusedApplication =
6958 std::make_shared<FakeApplicationHandle>();
6959 focusedApplication->setDispatchingTimeout(60ms);
6960 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
6961 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
6962 mFocusedWindow->setFocusable(false);
6963
6964 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6965 mFocusedWindow->consumeFocusEvent(false);
6966
6967 // Send a key. The ANR timer should start because there is no focused window.
6968 // 'focusedApplication' will get blamed if this timer completes.
6969 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006970 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006971 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6972 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6973 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05006975
6976 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
6977 // then the injected touches won't cause the focused event to get dropped.
6978 // The dispatcher only checks for whether the queue should be pruned upon queueing.
6979 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
6980 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
6981 // For this test, it means that the key would get delivered to the window once it becomes
6982 // focused.
6983 std::this_thread::sleep_for(10ms);
6984
6985 // Touch unfocused window. This should force the pending key to get dropped.
6986 NotifyMotionArgs motionArgs =
6987 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6988 ADISPLAY_ID_DEFAULT, {UNFOCUSED_WINDOW_LOCATION});
6989 mDispatcher->notifyMotion(&motionArgs);
6990
6991 // We do not consume the motion right away, because that would require dispatcher to first
6992 // process (== drop) the key event, and by that time, ANR will be raised.
6993 // Set the focused window first.
6994 mFocusedWindow->setFocusable(true);
6995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6996 setFocusedWindow(mFocusedWindow);
6997 mFocusedWindow->consumeFocusEvent(true);
6998 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
6999 // to another application. This could be a bug / behaviour in the policy.
7000
7001 mUnfocusedWindow->consumeMotionDown();
7002
7003 ASSERT_TRUE(mDispatcher->waitForIdle());
7004 // Should not ANR because we actually have a focused window. It was just added too slowly.
7005 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7006}
7007
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007008// These tests ensure we cannot send touch events to a window that's positioned behind a window
7009// that has feature NO_INPUT_CHANNEL.
7010// Layout:
7011// Top (closest to user)
7012// mNoInputWindow (above all windows)
7013// mBottomWindow
7014// Bottom (furthest from user)
7015class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7016 virtual void SetUp() override {
7017 InputDispatcherTest::SetUp();
7018
7019 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007020 mNoInputWindow =
7021 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7022 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007023 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007024 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007025 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7026 // It's perfectly valid for this window to not have an associated input channel
7027
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007028 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7029 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007030 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7031
7032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7033 }
7034
7035protected:
7036 std::shared_ptr<FakeApplicationHandle> mApplication;
7037 sp<FakeWindowHandle> mNoInputWindow;
7038 sp<FakeWindowHandle> mBottomWindow;
7039};
7040
7041TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7042 PointF touchedPoint = {10, 10};
7043
7044 NotifyMotionArgs motionArgs =
7045 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7046 ADISPLAY_ID_DEFAULT, {touchedPoint});
7047 mDispatcher->notifyMotion(&motionArgs);
7048
7049 mNoInputWindow->assertNoEvents();
7050 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7051 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7052 // and therefore should prevent mBottomWindow from receiving touches
7053 mBottomWindow->assertNoEvents();
7054}
7055
7056/**
7057 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7058 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7059 */
7060TEST_F(InputDispatcherMultiWindowOcclusionTests,
7061 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007062 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7063 "Window with input channel and NO_INPUT_CHANNEL",
7064 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007065
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007066 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007067 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7068 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7069
7070 PointF touchedPoint = {10, 10};
7071
7072 NotifyMotionArgs motionArgs =
7073 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7074 ADISPLAY_ID_DEFAULT, {touchedPoint});
7075 mDispatcher->notifyMotion(&motionArgs);
7076
7077 mNoInputWindow->assertNoEvents();
7078 mBottomWindow->assertNoEvents();
7079}
7080
Vishnu Nair958da932020-08-21 17:12:37 -07007081class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7082protected:
7083 std::shared_ptr<FakeApplicationHandle> mApp;
7084 sp<FakeWindowHandle> mWindow;
7085 sp<FakeWindowHandle> mMirror;
7086
7087 virtual void SetUp() override {
7088 InputDispatcherTest::SetUp();
7089 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007090 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7091 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7092 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007093 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7094 mWindow->setFocusable(true);
7095 mMirror->setFocusable(true);
7096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7097 }
7098};
7099
7100TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7101 // Request focus on a mirrored window
7102 setFocusedWindow(mMirror);
7103
7104 // window gets focused
7105 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7107 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007108 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7109}
7110
7111// A focused & mirrored window remains focused only if the window and its mirror are both
7112// focusable.
7113TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7114 setFocusedWindow(mMirror);
7115
7116 // window gets focused
7117 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7119 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007120 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7122 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007123 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7124
7125 mMirror->setFocusable(false);
7126 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7127
7128 // window loses focus since one of the windows associated with the token in not focusable
7129 mWindow->consumeFocusEvent(false);
7130
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007131 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7132 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007133 mWindow->assertNoEvents();
7134}
7135
7136// A focused & mirrored window remains focused until the window and its mirror both become
7137// invisible.
7138TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7139 setFocusedWindow(mMirror);
7140
7141 // window gets focused
7142 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7144 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007145 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7147 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007148 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7149
7150 mMirror->setVisible(false);
7151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7152
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7154 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007155 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7157 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007158 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7159
7160 mWindow->setVisible(false);
7161 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7162
7163 // window loses focus only after all windows associated with the token become invisible.
7164 mWindow->consumeFocusEvent(false);
7165
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007166 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7167 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007168 mWindow->assertNoEvents();
7169}
7170
7171// A focused & mirrored window remains focused until both windows are removed.
7172TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7173 setFocusedWindow(mMirror);
7174
7175 // window gets focused
7176 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7178 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007179 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7181 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007182 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7183
7184 // single window is removed but the window token remains focused
7185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7186
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7188 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007189 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7191 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007192 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7193
7194 // Both windows are removed
7195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7196 mWindow->consumeFocusEvent(false);
7197
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007198 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7199 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007200 mWindow->assertNoEvents();
7201}
7202
7203// Focus request can be pending until one window becomes visible.
7204TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7205 // Request focus on an invisible mirror.
7206 mWindow->setVisible(false);
7207 mMirror->setVisible(false);
7208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7209 setFocusedWindow(mMirror);
7210
7211 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007213 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7214 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007215
7216 mMirror->setVisible(true);
7217 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7218
7219 // window gets focused
7220 mWindow->consumeFocusEvent(true);
7221 // window gets the pending key event
7222 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7223}
Prabir Pradhan99987712020-11-10 18:43:05 -08007224
7225class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7226protected:
7227 std::shared_ptr<FakeApplicationHandle> mApp;
7228 sp<FakeWindowHandle> mWindow;
7229 sp<FakeWindowHandle> mSecondWindow;
7230
7231 void SetUp() override {
7232 InputDispatcherTest::SetUp();
7233 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007234 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007235 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007236 mSecondWindow =
7237 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007238 mSecondWindow->setFocusable(true);
7239
7240 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7242
7243 setFocusedWindow(mWindow);
7244 mWindow->consumeFocusEvent(true);
7245 }
7246
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007247 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
7248 const NotifyPointerCaptureChangedArgs args = generatePointerCaptureChangedArgs(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007249 mDispatcher->notifyPointerCaptureChanged(&args);
7250 }
7251
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007252 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7253 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007254 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007255 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7256 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007257 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007258 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007259 }
7260};
7261
7262TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7263 // Ensure that capture cannot be obtained for unfocused windows.
7264 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7265 mFakePolicy->assertSetPointerCaptureNotCalled();
7266 mSecondWindow->assertNoEvents();
7267
7268 // Ensure that capture can be enabled from the focus window.
7269 requestAndVerifyPointerCapture(mWindow, true);
7270
7271 // Ensure that capture cannot be disabled from a window that does not have capture.
7272 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7273 mFakePolicy->assertSetPointerCaptureNotCalled();
7274
7275 // Ensure that capture can be disabled from the window with capture.
7276 requestAndVerifyPointerCapture(mWindow, false);
7277}
7278
7279TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007280 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007281
7282 setFocusedWindow(mSecondWindow);
7283
7284 // Ensure that the capture disabled event was sent first.
7285 mWindow->consumeCaptureEvent(false);
7286 mWindow->consumeFocusEvent(false);
7287 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007288 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007289
7290 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007291 notifyPointerCaptureChanged({});
7292 notifyPointerCaptureChanged(request);
7293 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007294 mWindow->assertNoEvents();
7295 mSecondWindow->assertNoEvents();
7296 mFakePolicy->assertSetPointerCaptureNotCalled();
7297}
7298
7299TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007300 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007301
7302 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007303 notifyPointerCaptureChanged({});
7304 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007305
7306 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007307 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007308 mWindow->consumeCaptureEvent(false);
7309 mWindow->assertNoEvents();
7310}
7311
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007312TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7313 requestAndVerifyPointerCapture(mWindow, true);
7314
7315 // The first window loses focus.
7316 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007317 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007318 mWindow->consumeCaptureEvent(false);
7319
7320 // Request Pointer Capture from the second window before the notification from InputReader
7321 // arrives.
7322 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007323 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007324
7325 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007326 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007327
7328 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007329 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007330
7331 mSecondWindow->consumeFocusEvent(true);
7332 mSecondWindow->consumeCaptureEvent(true);
7333}
7334
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007335TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7336 // App repeatedly enables and disables capture.
7337 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7338 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7339 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7340 mFakePolicy->assertSetPointerCaptureCalled(false);
7341 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7342 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7343
7344 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7345 // first request is now stale, this should do nothing.
7346 notifyPointerCaptureChanged(firstRequest);
7347 mWindow->assertNoEvents();
7348
7349 // InputReader notifies that the second request was enabled.
7350 notifyPointerCaptureChanged(secondRequest);
7351 mWindow->consumeCaptureEvent(true);
7352}
7353
Prabir Pradhan7092e262022-05-03 16:51:09 +00007354TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7355 requestAndVerifyPointerCapture(mWindow, true);
7356
7357 // App toggles pointer capture off and on.
7358 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7359 mFakePolicy->assertSetPointerCaptureCalled(false);
7360
7361 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7362 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7363
7364 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7365 // preceding "disable" request.
7366 notifyPointerCaptureChanged(enableRequest);
7367
7368 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7369 // any notifications.
7370 mWindow->assertNoEvents();
7371}
7372
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007373class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7374protected:
7375 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007376
7377 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7378 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7379
7380 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7381 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7382
7383 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7384 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7385 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7386 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7387 MAXIMUM_OBSCURING_OPACITY);
7388
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007389 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007390 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007391 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007392
7393 sp<FakeWindowHandle> mTouchWindow;
7394
7395 virtual void SetUp() override {
7396 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007397 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007398 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7399 }
7400
7401 virtual void TearDown() override {
7402 InputDispatcherTest::TearDown();
7403 mTouchWindow.clear();
7404 }
7405
chaviw3277faf2021-05-19 16:45:23 -05007406 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7407 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007408 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007409 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007410 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007411 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007412 return window;
7413 }
7414
7415 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7416 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7417 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007418 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007419 // Generate an arbitrary PID based on the UID
7420 window->setOwnerInfo(1777 + (uid % 10000), uid);
7421 return window;
7422 }
7423
7424 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
7425 NotifyMotionArgs args =
7426 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
7427 ADISPLAY_ID_DEFAULT, points);
7428 mDispatcher->notifyMotion(&args);
7429 }
7430};
7431
7432TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007433 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007434 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007435 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007436
7437 touch();
7438
7439 mTouchWindow->assertNoEvents();
7440}
7441
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007442TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007443 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7444 const sp<FakeWindowHandle>& w =
7445 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7446 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7447
7448 touch();
7449
7450 mTouchWindow->assertNoEvents();
7451}
7452
7453TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007454 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7455 const sp<FakeWindowHandle>& w =
7456 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7458
7459 touch();
7460
7461 w->assertNoEvents();
7462}
7463
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007464TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007465 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7466 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007467
7468 touch();
7469
7470 mTouchWindow->consumeAnyMotionDown();
7471}
7472
7473TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007474 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007475 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007476 w->setFrame(Rect(0, 0, 50, 50));
7477 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007478
7479 touch({PointF{100, 100}});
7480
7481 mTouchWindow->consumeAnyMotionDown();
7482}
7483
7484TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007485 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007486 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7488
7489 touch();
7490
7491 mTouchWindow->consumeAnyMotionDown();
7492}
7493
7494TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7495 const sp<FakeWindowHandle>& w =
7496 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7497 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007498
7499 touch();
7500
7501 mTouchWindow->consumeAnyMotionDown();
7502}
7503
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007504TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7505 const sp<FakeWindowHandle>& w =
7506 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7507 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7508
7509 touch();
7510
7511 w->assertNoEvents();
7512}
7513
7514/**
7515 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7516 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7517 * window, the occluding window will still receive ACTION_OUTSIDE event.
7518 */
7519TEST_F(InputDispatcherUntrustedTouchesTest,
7520 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7521 const sp<FakeWindowHandle>& w =
7522 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007523 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7525
7526 touch();
7527
7528 w->consumeMotionOutside();
7529}
7530
7531TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7532 const sp<FakeWindowHandle>& w =
7533 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007534 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007535 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7536
7537 touch();
7538
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007539 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007540}
7541
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007542TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007543 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007544 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7545 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007546 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7547
7548 touch();
7549
7550 mTouchWindow->consumeAnyMotionDown();
7551}
7552
7553TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7554 const sp<FakeWindowHandle>& w =
7555 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7556 MAXIMUM_OBSCURING_OPACITY);
7557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007558
7559 touch();
7560
7561 mTouchWindow->consumeAnyMotionDown();
7562}
7563
7564TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007565 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007566 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7567 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7569
7570 touch();
7571
7572 mTouchWindow->assertNoEvents();
7573}
7574
7575TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7576 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7577 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007578 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7579 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007580 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007581 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7582 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007583 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7584
7585 touch();
7586
7587 mTouchWindow->assertNoEvents();
7588}
7589
7590TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7591 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7592 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007593 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7594 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007595 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007596 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7597 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007598 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7599
7600 touch();
7601
7602 mTouchWindow->consumeAnyMotionDown();
7603}
7604
7605TEST_F(InputDispatcherUntrustedTouchesTest,
7606 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7607 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007608 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7609 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007610 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007611 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7612 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007613 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7614
7615 touch();
7616
7617 mTouchWindow->consumeAnyMotionDown();
7618}
7619
7620TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7621 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007622 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7623 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007624 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007625 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7626 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007628
7629 touch();
7630
7631 mTouchWindow->assertNoEvents();
7632}
7633
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007634TEST_F(InputDispatcherUntrustedTouchesTest,
7635 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7636 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007637 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7638 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007639 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007640 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7641 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007642 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7643
7644 touch();
7645
7646 mTouchWindow->assertNoEvents();
7647}
7648
7649TEST_F(InputDispatcherUntrustedTouchesTest,
7650 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7651 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007652 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7653 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007654 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007655 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7656 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7658
7659 touch();
7660
7661 mTouchWindow->consumeAnyMotionDown();
7662}
7663
7664TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7665 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007666 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7667 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007668 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7669
7670 touch();
7671
7672 mTouchWindow->consumeAnyMotionDown();
7673}
7674
7675TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7676 const sp<FakeWindowHandle>& w =
7677 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7678 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7679
7680 touch();
7681
7682 mTouchWindow->consumeAnyMotionDown();
7683}
7684
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007685TEST_F(InputDispatcherUntrustedTouchesTest,
7686 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7687 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7688 const sp<FakeWindowHandle>& w =
7689 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7691
7692 touch();
7693
7694 mTouchWindow->assertNoEvents();
7695}
7696
7697TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7698 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7699 const sp<FakeWindowHandle>& w =
7700 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7702
7703 touch();
7704
7705 mTouchWindow->consumeAnyMotionDown();
7706}
7707
7708TEST_F(InputDispatcherUntrustedTouchesTest,
7709 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7710 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7711 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007712 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7713 OPACITY_ABOVE_THRESHOLD);
7714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7715
7716 touch();
7717
7718 mTouchWindow->consumeAnyMotionDown();
7719}
7720
7721TEST_F(InputDispatcherUntrustedTouchesTest,
7722 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7723 const sp<FakeWindowHandle>& w1 =
7724 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7725 OPACITY_BELOW_THRESHOLD);
7726 const sp<FakeWindowHandle>& w2 =
7727 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7728 OPACITY_BELOW_THRESHOLD);
7729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7730
7731 touch();
7732
7733 mTouchWindow->assertNoEvents();
7734}
7735
7736/**
7737 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7738 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7739 * (which alone would result in allowing touches) does not affect the blocking behavior.
7740 */
7741TEST_F(InputDispatcherUntrustedTouchesTest,
7742 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7743 const sp<FakeWindowHandle>& wB =
7744 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7745 OPACITY_BELOW_THRESHOLD);
7746 const sp<FakeWindowHandle>& wC =
7747 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7748 OPACITY_BELOW_THRESHOLD);
7749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7750
7751 touch();
7752
7753 mTouchWindow->assertNoEvents();
7754}
7755
7756/**
7757 * This test is testing that a window from a different UID but with same application token doesn't
7758 * block the touch. Apps can share the application token for close UI collaboration for example.
7759 */
7760TEST_F(InputDispatcherUntrustedTouchesTest,
7761 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7762 const sp<FakeWindowHandle>& w =
7763 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7764 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007765 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7766
7767 touch();
7768
7769 mTouchWindow->consumeAnyMotionDown();
7770}
7771
arthurhungb89ccb02020-12-30 16:19:01 +08007772class InputDispatcherDragTests : public InputDispatcherTest {
7773protected:
7774 std::shared_ptr<FakeApplicationHandle> mApp;
7775 sp<FakeWindowHandle> mWindow;
7776 sp<FakeWindowHandle> mSecondWindow;
7777 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007778 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007779 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7780 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007781
7782 void SetUp() override {
7783 InputDispatcherTest::SetUp();
7784 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007785 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007786 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007787
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007788 mSecondWindow =
7789 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007790 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007791
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007792 mSpyWindow =
7793 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007794 mSpyWindow->setSpy(true);
7795 mSpyWindow->setTrustedOverlay(true);
7796 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7797
arthurhungb89ccb02020-12-30 16:19:01 +08007798 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007800 }
7801
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007802 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7803 switch (fromSource) {
7804 case AINPUT_SOURCE_TOUCHSCREEN:
7805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7806 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7807 ADISPLAY_ID_DEFAULT, {50, 50}))
7808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7809 break;
7810 case AINPUT_SOURCE_STYLUS:
7811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7812 injectMotionEvent(
7813 mDispatcher,
7814 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7815 AINPUT_SOURCE_STYLUS)
7816 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
7817 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7818 .x(50)
7819 .y(50))
7820 .build()));
7821 break;
7822 case AINPUT_SOURCE_MOUSE:
7823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7824 injectMotionEvent(
7825 mDispatcher,
7826 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7827 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7828 .pointer(PointerBuilder(MOUSE_POINTER_ID,
7829 AMOTION_EVENT_TOOL_TYPE_MOUSE)
7830 .x(50)
7831 .y(50))
7832 .build()));
7833 break;
7834 default:
7835 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7836 }
arthurhungb89ccb02020-12-30 16:19:01 +08007837
7838 // Window should receive motion event.
7839 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007840 // Spy window should also receive motion event
7841 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007842 }
7843
7844 // Start performing drag, we will create a drag window and transfer touch to it.
7845 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7846 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007847 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007848 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007849 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00007850 }
arthurhungb89ccb02020-12-30 16:19:01 +08007851
7852 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007853 mDragWindow =
7854 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007855 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08007856 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007857 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007858
7859 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00007860 bool transferred =
7861 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00007862 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00007863 if (transferred) {
7864 mWindow->consumeMotionCancel();
7865 mDragWindow->consumeMotionDown();
7866 }
7867 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08007868 }
7869};
7870
7871TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007872 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08007873
7874 // Move on window.
7875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7876 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7877 ADISPLAY_ID_DEFAULT, {50, 50}))
7878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7879 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7880 mWindow->consumeDragEvent(false, 50, 50);
7881 mSecondWindow->assertNoEvents();
7882
7883 // Move to another window.
7884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7885 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7886 ADISPLAY_ID_DEFAULT, {150, 50}))
7887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7888 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7889 mWindow->consumeDragEvent(true, 150, 50);
7890 mSecondWindow->consumeDragEvent(false, 50, 50);
7891
7892 // Move back to original window.
7893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7894 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7895 ADISPLAY_ID_DEFAULT, {50, 50}))
7896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7897 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7898 mWindow->consumeDragEvent(false, 50, 50);
7899 mSecondWindow->consumeDragEvent(true, -50, 50);
7900
7901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7902 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
7903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7904 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7905 mWindow->assertNoEvents();
7906 mSecondWindow->assertNoEvents();
7907}
7908
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007909TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007910 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007911
7912 // No cancel event after drag start
7913 mSpyWindow->assertNoEvents();
7914
7915 const MotionEvent secondFingerDownEvent =
7916 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7917 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00007918 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
7919 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007920 .build();
7921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7922 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
7923 InputEventInjectionSync::WAIT_FOR_RESULT))
7924 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7925
7926 // Receives cancel for first pointer after next pointer down
7927 mSpyWindow->consumeMotionCancel();
7928 mSpyWindow->consumeMotionDown();
7929
7930 mSpyWindow->assertNoEvents();
7931}
7932
arthurhungf452d0b2021-01-06 00:19:52 +08007933TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007934 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08007935
7936 // Move on window.
7937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7938 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7939 ADISPLAY_ID_DEFAULT, {50, 50}))
7940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7941 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7942 mWindow->consumeDragEvent(false, 50, 50);
7943 mSecondWindow->assertNoEvents();
7944
7945 // Move to another window.
7946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7947 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7948 ADISPLAY_ID_DEFAULT, {150, 50}))
7949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7950 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7951 mWindow->consumeDragEvent(true, 150, 50);
7952 mSecondWindow->consumeDragEvent(false, 50, 50);
7953
7954 // drop to another window.
7955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7956 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7957 {150, 50}))
7958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7959 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
7960 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7961 mWindow->assertNoEvents();
7962 mSecondWindow->assertNoEvents();
7963}
7964
arthurhung6d4bed92021-03-17 11:59:33 +08007965TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007966 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08007967
7968 // Move on window and keep button pressed.
7969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7970 injectMotionEvent(mDispatcher,
7971 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7972 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
7973 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7974 .x(50)
7975 .y(50))
7976 .build()))
7977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7978 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7979 mWindow->consumeDragEvent(false, 50, 50);
7980 mSecondWindow->assertNoEvents();
7981
7982 // Move to another window and release button, expect to drop item.
7983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7984 injectMotionEvent(mDispatcher,
7985 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
7986 .buttonState(0)
7987 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
7988 .x(150)
7989 .y(50))
7990 .build()))
7991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7992 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
7993 mWindow->assertNoEvents();
7994 mSecondWindow->assertNoEvents();
7995 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
7996
7997 // nothing to the window.
7998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7999 injectMotionEvent(mDispatcher,
8000 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8001 .buttonState(0)
8002 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_STYLUS)
8003 .x(150)
8004 .y(50))
8005 .build()))
8006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8007 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8008 mWindow->assertNoEvents();
8009 mSecondWindow->assertNoEvents();
8010}
8011
Arthur Hung54745652022-04-20 07:17:41 +00008012TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008013 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008014
8015 // Set second window invisible.
8016 mSecondWindow->setVisible(false);
8017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8018
8019 // Move on window.
8020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8021 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8022 ADISPLAY_ID_DEFAULT, {50, 50}))
8023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8024 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8025 mWindow->consumeDragEvent(false, 50, 50);
8026 mSecondWindow->assertNoEvents();
8027
8028 // Move to another window.
8029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8030 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8031 ADISPLAY_ID_DEFAULT, {150, 50}))
8032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8033 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8034 mWindow->consumeDragEvent(true, 150, 50);
8035 mSecondWindow->assertNoEvents();
8036
8037 // drop to another window.
8038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8039 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8040 {150, 50}))
8041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8042 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8043 mFakePolicy->assertDropTargetEquals(nullptr);
8044 mWindow->assertNoEvents();
8045 mSecondWindow->assertNoEvents();
8046}
8047
Arthur Hung54745652022-04-20 07:17:41 +00008048TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008049 // Ensure window could track pointerIds if it didn't support split touch.
8050 mWindow->setPreventSplitting(true);
8051
Arthur Hung54745652022-04-20 07:17:41 +00008052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8053 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8054 {50, 50}))
8055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8056 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8057
8058 const MotionEvent secondFingerDownEvent =
8059 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8060 .displayId(ADISPLAY_ID_DEFAULT)
8061 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008062 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8063 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008064 .build();
8065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8066 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8067 InputEventInjectionSync::WAIT_FOR_RESULT))
8068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008069 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008070
8071 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008072 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008073}
8074
8075TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8076 // First down on second window.
8077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8078 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8079 {150, 50}))
8080 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8081
8082 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8083
8084 // Second down on first window.
8085 const MotionEvent secondFingerDownEvent =
8086 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8087 .displayId(ADISPLAY_ID_DEFAULT)
8088 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008089 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8090 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008091 .build();
8092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8093 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8094 InputEventInjectionSync::WAIT_FOR_RESULT))
8095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8096 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8097
8098 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008099 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008100
8101 // Move on window.
8102 const MotionEvent secondFingerMoveEvent =
8103 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8104 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008105 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8106 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008107 .build();
8108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8109 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8110 InputEventInjectionSync::WAIT_FOR_RESULT));
8111 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8112 mWindow->consumeDragEvent(false, 50, 50);
8113 mSecondWindow->consumeMotionMove();
8114
8115 // Release the drag pointer should perform drop.
8116 const MotionEvent secondFingerUpEvent =
8117 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8118 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008119 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
8120 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008121 .build();
8122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8123 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8124 InputEventInjectionSync::WAIT_FOR_RESULT));
8125 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8126 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8127 mWindow->assertNoEvents();
8128 mSecondWindow->consumeMotionMove();
8129}
8130
Arthur Hung3915c1f2022-05-31 07:17:17 +00008131TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008132 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008133
8134 // Update window of second display.
8135 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008136 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008137 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8138
8139 // Let second display has a touch state.
8140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8141 injectMotionEvent(mDispatcher,
8142 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8143 AINPUT_SOURCE_TOUCHSCREEN)
8144 .displayId(SECOND_DISPLAY_ID)
8145 .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER)
8146 .x(100)
8147 .y(100))
8148 .build()));
8149 windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008150 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008151 // Update window again.
8152 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8153
8154 // Move on window.
8155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8156 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8157 ADISPLAY_ID_DEFAULT, {50, 50}))
8158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8159 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8160 mWindow->consumeDragEvent(false, 50, 50);
8161 mSecondWindow->assertNoEvents();
8162
8163 // Move to another window.
8164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8165 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8166 ADISPLAY_ID_DEFAULT, {150, 50}))
8167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8168 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8169 mWindow->consumeDragEvent(true, 150, 50);
8170 mSecondWindow->consumeDragEvent(false, 50, 50);
8171
8172 // drop to another window.
8173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8174 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8175 {150, 50}))
8176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8177 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8178 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8179 mWindow->assertNoEvents();
8180 mSecondWindow->assertNoEvents();
8181}
8182
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008183TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8184 startDrag(true, AINPUT_SOURCE_MOUSE);
8185 // Move on window.
8186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8187 injectMotionEvent(mDispatcher,
8188 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8189 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8190 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8191 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8192 .x(50)
8193 .y(50))
8194 .build()))
8195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8196 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8197 mWindow->consumeDragEvent(false, 50, 50);
8198 mSecondWindow->assertNoEvents();
8199
8200 // Move to another window.
8201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8202 injectMotionEvent(mDispatcher,
8203 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8204 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8205 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8206 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8207 .x(150)
8208 .y(50))
8209 .build()))
8210 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8211 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8212 mWindow->consumeDragEvent(true, 150, 50);
8213 mSecondWindow->consumeDragEvent(false, 50, 50);
8214
8215 // drop to another window.
8216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8217 injectMotionEvent(mDispatcher,
8218 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8219 .buttonState(0)
8220 .pointer(PointerBuilder(MOUSE_POINTER_ID,
8221 AMOTION_EVENT_TOOL_TYPE_MOUSE)
8222 .x(150)
8223 .y(50))
8224 .build()))
8225 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8226 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8227 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8228 mWindow->assertNoEvents();
8229 mSecondWindow->assertNoEvents();
8230}
8231
Vishnu Nair062a8672021-09-03 16:07:44 -07008232class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8233
8234TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008236 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8237 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008238 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008239 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8240 window->setFocusable(true);
8241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8242 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008243 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008244
8245 // With the flag set, window should not get any input
8246 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8247 mDispatcher->notifyKey(&keyArgs);
8248 window->assertNoEvents();
8249
8250 NotifyMotionArgs motionArgs =
8251 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8252 ADISPLAY_ID_DEFAULT);
8253 mDispatcher->notifyMotion(&motionArgs);
8254 window->assertNoEvents();
8255
8256 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008257 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008258 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8259
8260 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8261 mDispatcher->notifyKey(&keyArgs);
8262 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8263
8264 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8265 ADISPLAY_ID_DEFAULT);
8266 mDispatcher->notifyMotion(&motionArgs);
8267 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8268 window->assertNoEvents();
8269}
8270
8271TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8272 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8273 std::make_shared<FakeApplicationHandle>();
8274 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008275 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8276 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008277 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8278 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008279 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008281 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8282 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008283 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008284 window->setOwnerInfo(222, 222);
8285 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8286 window->setFocusable(true);
8287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8288 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008289 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008290
8291 // With the flag set, window should not get any input
8292 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8293 mDispatcher->notifyKey(&keyArgs);
8294 window->assertNoEvents();
8295
8296 NotifyMotionArgs motionArgs =
8297 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8298 ADISPLAY_ID_DEFAULT);
8299 mDispatcher->notifyMotion(&motionArgs);
8300 window->assertNoEvents();
8301
8302 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008303 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8305
8306 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8307 mDispatcher->notifyKey(&keyArgs);
8308 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8309
8310 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8311 ADISPLAY_ID_DEFAULT);
8312 mDispatcher->notifyMotion(&motionArgs);
8313 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8314 window->assertNoEvents();
8315}
8316
8317TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8318 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8319 std::make_shared<FakeApplicationHandle>();
8320 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008321 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8322 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008323 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8324 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008325 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008327 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8328 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008329 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008330 window->setOwnerInfo(222, 222);
8331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8332 window->setFocusable(true);
8333 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8334 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008335 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008336
8337 // With the flag set, window should not get any input
8338 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
8339 mDispatcher->notifyKey(&keyArgs);
8340 window->assertNoEvents();
8341
8342 NotifyMotionArgs motionArgs =
8343 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8344 ADISPLAY_ID_DEFAULT);
8345 mDispatcher->notifyMotion(&motionArgs);
8346 window->assertNoEvents();
8347
8348 // When the window is no longer obscured because it went on top, it should get input
8349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8350
8351 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
8352 mDispatcher->notifyKey(&keyArgs);
8353 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8354
8355 motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8356 ADISPLAY_ID_DEFAULT);
8357 mDispatcher->notifyMotion(&motionArgs);
8358 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8359 window->assertNoEvents();
8360}
8361
Antonio Kantekf16f2832021-09-28 04:39:20 +00008362class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8363protected:
8364 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008365 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008366 sp<FakeWindowHandle> mWindow;
8367 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008368 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008369
8370 void SetUp() override {
8371 InputDispatcherTest::SetUp();
8372
8373 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008374 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008375 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008376 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008377 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008378 mSecondWindow =
8379 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008380 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008381 mThirdWindow =
8382 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8383 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8384 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008385
8386 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8388 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8389 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008390 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008391
Antonio Kantek15beb512022-06-13 22:35:41 +00008392 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008393 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008394 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008395 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8396 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008397 mThirdWindow->assertNoEvents();
8398 }
8399
8400 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8401 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008402 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008403 SECOND_DISPLAY_ID)) {
8404 mWindow->assertNoEvents();
8405 mSecondWindow->assertNoEvents();
8406 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008407 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008408 }
8409
Antonio Kantek15beb512022-06-13 22:35:41 +00008410 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8411 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008412 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8413 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008414 mWindow->consumeTouchModeEvent(inTouchMode);
8415 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008416 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008417 }
8418};
8419
Antonio Kantek26defcf2022-02-08 01:12:27 +00008420TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008421 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008422 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8423 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008424 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008425}
8426
Antonio Kantek26defcf2022-02-08 01:12:27 +00008427TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8428 const WindowInfo& windowInfo = *mWindow->getInfo();
8429 int32_t ownerPid = windowInfo.ownerPid;
8430 int32_t ownerUid = windowInfo.ownerUid;
8431 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8432 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008433 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008434 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008435 mWindow->assertNoEvents();
8436 mSecondWindow->assertNoEvents();
8437}
8438
8439TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8440 const WindowInfo& windowInfo = *mWindow->getInfo();
8441 int32_t ownerPid = windowInfo.ownerPid;
8442 int32_t ownerUid = windowInfo.ownerUid;
8443 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008444 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008445 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008446}
8447
Antonio Kantekf16f2832021-09-28 04:39:20 +00008448TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008449 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008450 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8451 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008452 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008453 mWindow->assertNoEvents();
8454 mSecondWindow->assertNoEvents();
8455}
8456
Antonio Kantek15beb512022-06-13 22:35:41 +00008457TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8458 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8459 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8460 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008461 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008462 mWindow->assertNoEvents();
8463 mSecondWindow->assertNoEvents();
8464 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8465}
8466
Antonio Kantek48710e42022-03-24 14:19:30 -07008467TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8468 // Interact with the window first.
8469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8470 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8471 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8472
8473 // Then remove focus.
8474 mWindow->setFocusable(false);
8475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8476
8477 // Assert that caller can switch touch mode by owning one of the last interacted window.
8478 const WindowInfo& windowInfo = *mWindow->getInfo();
8479 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8480 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008481 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008482}
8483
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008484class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8485public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008486 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008487 std::shared_ptr<FakeApplicationHandle> application =
8488 std::make_shared<FakeApplicationHandle>();
8489 std::string name = "Fake Spy ";
8490 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008491 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8492 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008493 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008494 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008495 return spy;
8496 }
8497
8498 sp<FakeWindowHandle> createForeground() {
8499 std::shared_ptr<FakeApplicationHandle> application =
8500 std::make_shared<FakeApplicationHandle>();
8501 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008502 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8503 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008504 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008505 return window;
8506 }
8507
8508private:
8509 int mSpyCount{0};
8510};
8511
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008512using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008513/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008514 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8515 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008516TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8517 ScopedSilentDeath _silentDeath;
8518
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008519 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008520 spy->setTrustedOverlay(false);
8521 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8522 ".* not a trusted overlay");
8523}
8524
8525/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008526 * Input injection into a display with a spy window but no foreground windows should succeed.
8527 */
8528TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008529 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008530 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8531
8532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8533 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8535 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8536}
8537
8538/**
8539 * Verify the order in which different input windows receive events. The touched foreground window
8540 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8541 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8542 * receive events before ones belows it.
8543 *
8544 * Here, we set up a scenario with four windows in the following Z order from the top:
8545 * spy1, spy2, window, spy3.
8546 * We then inject an event and verify that the foreground "window" receives it first, followed by
8547 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8548 * window.
8549 */
8550TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8551 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008552 auto spy1 = createSpy();
8553 auto spy2 = createSpy();
8554 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8556 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8557 const size_t numChannels = channels.size();
8558
Michael Wright8e9a8562022-02-09 13:44:29 +00008559 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008560 if (!epollFd.ok()) {
8561 FAIL() << "Failed to create epoll fd";
8562 }
8563
8564 for (size_t i = 0; i < numChannels; i++) {
8565 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8566 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8567 FAIL() << "Failed to add fd to epoll";
8568 }
8569 }
8570
8571 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8572 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8574
8575 std::vector<size_t> eventOrder;
8576 std::vector<struct epoll_event> events(numChannels);
8577 for (;;) {
8578 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8579 (100ms).count());
8580 if (nFds < 0) {
8581 FAIL() << "Failed to call epoll_wait";
8582 }
8583 if (nFds == 0) {
8584 break; // epoll_wait timed out
8585 }
8586 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008587 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008588 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008589 channels[i]->consumeMotionDown();
8590 }
8591 }
8592
8593 // Verify the order in which the events were received.
8594 EXPECT_EQ(3u, eventOrder.size());
8595 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8596 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8597 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8598}
8599
8600/**
8601 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8602 */
8603TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8604 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008605 auto spy = createSpy();
8606 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8608
8609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8610 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8612 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8613 spy->assertNoEvents();
8614}
8615
8616/**
8617 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8618 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8619 * to the window.
8620 */
8621TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8622 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008623 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008624 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8626
8627 // Inject an event outside the spy window's touchable region.
8628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8629 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8630 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8631 window->consumeMotionDown();
8632 spy->assertNoEvents();
8633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8634 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8636 window->consumeMotionUp();
8637 spy->assertNoEvents();
8638
8639 // Inject an event inside the spy window's touchable region.
8640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8641 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8642 {5, 10}))
8643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8644 window->consumeMotionDown();
8645 spy->consumeMotionDown();
8646}
8647
8648/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008649 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008650 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008651 */
8652TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8653 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008654 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008655 auto spy = createSpy();
8656 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008657 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008658 spy->setFrame(Rect{0, 0, 20, 20});
8659 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8660
8661 // Inject an event outside the spy window's frame and touchable region.
8662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008663 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8664 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8666 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008667 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008668}
8669
8670/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008671 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8672 * pointers that are down within its bounds.
8673 */
8674TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8675 auto windowLeft = createForeground();
8676 windowLeft->setFrame({0, 0, 100, 200});
8677 auto windowRight = createForeground();
8678 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008679 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008680 spy->setFrame({0, 0, 200, 200});
8681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8682
8683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8684 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8685 {50, 50}))
8686 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8687 windowLeft->consumeMotionDown();
8688 spy->consumeMotionDown();
8689
8690 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008691 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008692 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008693 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8694 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008695 .build();
8696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8697 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8698 InputEventInjectionSync::WAIT_FOR_RESULT))
8699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8700 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008701 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008702}
8703
8704/**
8705 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8706 * the spy should receive the second pointer with ACTION_DOWN.
8707 */
8708TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8709 auto window = createForeground();
8710 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008711 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008712 spyRight->setFrame({100, 0, 200, 200});
8713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8714
8715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8716 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8717 {50, 50}))
8718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8719 window->consumeMotionDown();
8720 spyRight->assertNoEvents();
8721
8722 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008723 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008724 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008725 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8726 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008727 .build();
8728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8729 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8730 InputEventInjectionSync::WAIT_FOR_RESULT))
8731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008732 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008733 spyRight->consumeMotionDown();
8734}
8735
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008736/**
8737 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8738 * windows should be allowed to control split touch.
8739 */
8740TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008741 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008742 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008743 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008744 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008745
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008746 auto window = createForeground();
8747 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008748
8749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8750
8751 // First finger down, no window touched.
8752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8753 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8754 {100, 200}))
8755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8756 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8757 window->assertNoEvents();
8758
8759 // Second finger down on window, the window should receive touch down.
8760 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008761 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008762 .displayId(ADISPLAY_ID_DEFAULT)
8763 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008764 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8765 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008766 .build();
8767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8768 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8769 InputEventInjectionSync::WAIT_FOR_RESULT))
8770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8771
8772 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008773 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008774}
8775
8776/**
8777 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8778 * do not receive key events.
8779 */
8780TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008781 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008782 spy->setFocusable(false);
8783
8784 auto window = createForeground();
8785 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8786 setFocusedWindow(window);
8787 window->consumeFocusEvent(true);
8788
8789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8790 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8791 window->consumeKeyDown(ADISPLAY_ID_NONE);
8792
8793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8794 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8795 window->consumeKeyUp(ADISPLAY_ID_NONE);
8796
8797 spy->assertNoEvents();
8798}
8799
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008800using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8801
8802/**
8803 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8804 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8805 */
8806TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8807 auto window = createForeground();
8808 auto spy1 = createSpy();
8809 auto spy2 = createSpy();
8810 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8811
8812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8813 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8815 window->consumeMotionDown();
8816 spy1->consumeMotionDown();
8817 spy2->consumeMotionDown();
8818
8819 // Pilfer pointers from the second spy window.
8820 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8821 spy2->assertNoEvents();
8822 spy1->consumeMotionCancel();
8823 window->consumeMotionCancel();
8824
8825 // The rest of the gesture should only be sent to the second spy window.
8826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8827 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8828 ADISPLAY_ID_DEFAULT))
8829 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8830 spy2->consumeMotionMove();
8831 spy1->assertNoEvents();
8832 window->assertNoEvents();
8833}
8834
8835/**
8836 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8837 * in the middle of the gesture.
8838 */
8839TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8840 auto window = createForeground();
8841 auto spy = createSpy();
8842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8843
8844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8845 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8847 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8848 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8849
8850 window->releaseChannel();
8851
8852 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8853
8854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8855 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8857 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8858}
8859
8860/**
8861 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8862 * the spy, but not to any other windows.
8863 */
8864TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8865 auto spy = createSpy();
8866 auto window = createForeground();
8867
8868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8869
8870 // First finger down on the window and the spy.
8871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8872 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8873 {100, 200}))
8874 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8875 spy->consumeMotionDown();
8876 window->consumeMotionDown();
8877
8878 // Spy window pilfers the pointers.
8879 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8880 window->consumeMotionCancel();
8881
8882 // Second finger down on the window and spy, but the window should not receive the pointer down.
8883 const MotionEvent secondFingerDownEvent =
8884 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8885 .displayId(ADISPLAY_ID_DEFAULT)
8886 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008887 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8888 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008889 .build();
8890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8891 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8892 InputEventInjectionSync::WAIT_FOR_RESULT))
8893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8894
Harry Cutts33476232023-01-30 19:57:29 +00008895 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008896
8897 // Third finger goes down outside all windows, so injection should fail.
8898 const MotionEvent thirdFingerDownEvent =
8899 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8900 .displayId(ADISPLAY_ID_DEFAULT)
8901 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008902 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(100).y(200))
8903 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
8904 .pointer(PointerBuilder(/*id=*/2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008905 .build();
8906 ASSERT_EQ(InputEventInjectionResult::FAILED,
8907 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8908 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008909 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008910
8911 spy->assertNoEvents();
8912 window->assertNoEvents();
8913}
8914
8915/**
8916 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
8917 */
8918TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
8919 auto spy = createSpy();
8920 spy->setFrame(Rect(0, 0, 100, 100));
8921 auto window = createForeground();
8922 window->setFrame(Rect(0, 0, 200, 200));
8923
8924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8925
8926 // First finger down on the window only
8927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8928 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8929 {150, 150}))
8930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8931 window->consumeMotionDown();
8932
8933 // Second finger down on the spy and window
8934 const MotionEvent secondFingerDownEvent =
8935 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8936 .displayId(ADISPLAY_ID_DEFAULT)
8937 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008938 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
8939 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008940 .build();
8941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8942 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8943 InputEventInjectionSync::WAIT_FOR_RESULT))
8944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8945 spy->consumeMotionDown();
8946 window->consumeMotionPointerDown(1);
8947
8948 // Third finger down on the spy and window
8949 const MotionEvent thirdFingerDownEvent =
8950 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8951 .displayId(ADISPLAY_ID_DEFAULT)
8952 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008953 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
8954 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
8955 .pointer(PointerBuilder(/*id=*/2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008956 .build();
8957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8958 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
8959 InputEventInjectionSync::WAIT_FOR_RESULT))
8960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8961 spy->consumeMotionPointerDown(1);
8962 window->consumeMotionPointerDown(2);
8963
8964 // Spy window pilfers the pointers.
8965 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8966 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8967 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
8968
8969 spy->assertNoEvents();
8970 window->assertNoEvents();
8971}
8972
8973/**
8974 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
8975 * other windows should be canceled. If this results in the cancellation of all pointers for some
8976 * window, then that window should receive ACTION_CANCEL.
8977 */
8978TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
8979 auto spy = createSpy();
8980 spy->setFrame(Rect(0, 0, 100, 100));
8981 auto window = createForeground();
8982 window->setFrame(Rect(0, 0, 200, 200));
8983
8984 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8985
8986 // First finger down on both spy and window
8987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8988 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8989 {10, 10}))
8990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8991 window->consumeMotionDown();
8992 spy->consumeMotionDown();
8993
8994 // Second finger down on the spy and window
8995 const MotionEvent secondFingerDownEvent =
8996 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8997 .displayId(ADISPLAY_ID_DEFAULT)
8998 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00008999 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
9000 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009001 .build();
9002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9003 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9004 InputEventInjectionSync::WAIT_FOR_RESULT))
9005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9006 spy->consumeMotionPointerDown(1);
9007 window->consumeMotionPointerDown(1);
9008
9009 // Spy window pilfers the pointers.
9010 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9011 window->consumeMotionCancel();
9012
9013 spy->assertNoEvents();
9014 window->assertNoEvents();
9015}
9016
9017/**
9018 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9019 * be sent to other windows
9020 */
9021TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9022 auto spy = createSpy();
9023 spy->setFrame(Rect(0, 0, 100, 100));
9024 auto window = createForeground();
9025 window->setFrame(Rect(0, 0, 200, 200));
9026
9027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9028
9029 // First finger down on both window and spy
9030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9031 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9032 {10, 10}))
9033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9034 window->consumeMotionDown();
9035 spy->consumeMotionDown();
9036
9037 // Spy window pilfers the pointers.
9038 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9039 window->consumeMotionCancel();
9040
9041 // Second finger down on the window only
9042 const MotionEvent secondFingerDownEvent =
9043 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9044 .displayId(ADISPLAY_ID_DEFAULT)
9045 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts33476232023-01-30 19:57:29 +00009046 .pointer(PointerBuilder(/*id=*/0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
9047 .pointer(PointerBuilder(/*id=*/1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009048 .build();
9049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9050 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9051 InputEventInjectionSync::WAIT_FOR_RESULT))
9052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9053 window->consumeMotionDown();
9054 window->assertNoEvents();
9055
9056 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9057 spy->consumeMotionMove();
9058 spy->assertNoEvents();
9059}
9060
Prabir Pradhand65552b2021-10-07 11:23:50 -07009061class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9062public:
9063 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9064 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9065 std::make_shared<FakeApplicationHandle>();
9066 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009067 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9068 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009069 overlay->setFocusable(false);
9070 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009071 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009072 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009073 overlay->setTrustedOverlay(true);
9074
9075 std::shared_ptr<FakeApplicationHandle> application =
9076 std::make_shared<FakeApplicationHandle>();
9077 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009078 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9079 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009080 window->setFocusable(true);
9081 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009082
9083 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9084 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9085 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009086 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009087 return {std::move(overlay), std::move(window)};
9088 }
9089
9090 void sendFingerEvent(int32_t action) {
9091 NotifyMotionArgs motionArgs =
9092 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9093 ADISPLAY_ID_DEFAULT, {PointF{20, 20}});
9094 mDispatcher->notifyMotion(&motionArgs);
9095 }
9096
9097 void sendStylusEvent(int32_t action) {
9098 NotifyMotionArgs motionArgs =
9099 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9100 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
9101 motionArgs.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
9102 mDispatcher->notifyMotion(&motionArgs);
9103 }
9104};
9105
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009106using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9107
9108TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9109 ScopedSilentDeath _silentDeath;
9110
Prabir Pradhand65552b2021-10-07 11:23:50 -07009111 auto [overlay, window] = setupStylusOverlayScenario();
9112 overlay->setTrustedOverlay(false);
9113 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9114 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9115 ".* not a trusted overlay");
9116}
9117
9118TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9119 auto [overlay, window] = setupStylusOverlayScenario();
9120 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9121
9122 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9123 overlay->consumeMotionDown();
9124 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9125 overlay->consumeMotionUp();
9126
9127 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9128 window->consumeMotionDown();
9129 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9130 window->consumeMotionUp();
9131
9132 overlay->assertNoEvents();
9133 window->assertNoEvents();
9134}
9135
9136TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9137 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009138 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009139 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9140
9141 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9142 overlay->consumeMotionDown();
9143 window->consumeMotionDown();
9144 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9145 overlay->consumeMotionUp();
9146 window->consumeMotionUp();
9147
9148 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9149 window->consumeMotionDown();
9150 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9151 window->consumeMotionUp();
9152
9153 overlay->assertNoEvents();
9154 window->assertNoEvents();
9155}
9156
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009157/**
9158 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9159 * The scenario is as follows:
9160 * - The stylus interceptor overlay is configured as a spy window.
9161 * - The stylus interceptor spy receives the start of a new stylus gesture.
9162 * - It pilfers pointers and then configures itself to no longer be a spy.
9163 * - The stylus interceptor continues to receive the rest of the gesture.
9164 */
9165TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9166 auto [overlay, window] = setupStylusOverlayScenario();
9167 overlay->setSpy(true);
9168 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9169
9170 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9171 overlay->consumeMotionDown();
9172 window->consumeMotionDown();
9173
9174 // The interceptor pilfers the pointers.
9175 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9176 window->consumeMotionCancel();
9177
9178 // The interceptor configures itself so that it is no longer a spy.
9179 overlay->setSpy(false);
9180 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9181
9182 // It continues to receive the rest of the stylus gesture.
9183 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9184 overlay->consumeMotionMove();
9185 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9186 overlay->consumeMotionUp();
9187
9188 window->assertNoEvents();
9189}
9190
Prabir Pradhan5735a322022-04-11 17:23:34 +00009191struct User {
9192 int32_t mPid;
9193 int32_t mUid;
9194 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9195 std::unique_ptr<InputDispatcher>& mDispatcher;
9196
9197 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9198 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9199
9200 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9201 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9202 ADISPLAY_ID_DEFAULT, {100, 200},
9203 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9204 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9205 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9206 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9207 }
9208
9209 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009210 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009211 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009212 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009213 mPolicyFlags);
9214 }
9215
9216 sp<FakeWindowHandle> createWindow() const {
9217 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9218 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009219 sp<FakeWindowHandle> window =
9220 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9221 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009222 window->setOwnerInfo(mPid, mUid);
9223 return window;
9224 }
9225};
9226
9227using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9228
9229TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9230 auto owner = User(mDispatcher, 10, 11);
9231 auto window = owner.createWindow();
9232 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9233
9234 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9235 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9236 window->consumeMotionDown();
9237
9238 setFocusedWindow(window);
9239 window->consumeFocusEvent(true);
9240
9241 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9242 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9243 window->consumeKeyDown(ADISPLAY_ID_NONE);
9244}
9245
9246TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9247 auto owner = User(mDispatcher, 10, 11);
9248 auto window = owner.createWindow();
9249 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9250
9251 auto rando = User(mDispatcher, 20, 21);
9252 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9253 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9254
9255 setFocusedWindow(window);
9256 window->consumeFocusEvent(true);
9257
9258 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9259 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9260 window->assertNoEvents();
9261}
9262
9263TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9264 auto owner = User(mDispatcher, 10, 11);
9265 auto window = owner.createWindow();
9266 auto spy = owner.createWindow();
9267 spy->setSpy(true);
9268 spy->setTrustedOverlay(true);
9269 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9270
9271 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9272 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9273 spy->consumeMotionDown();
9274 window->consumeMotionDown();
9275}
9276
9277TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9278 auto owner = User(mDispatcher, 10, 11);
9279 auto window = owner.createWindow();
9280
9281 auto rando = User(mDispatcher, 20, 21);
9282 auto randosSpy = rando.createWindow();
9283 randosSpy->setSpy(true);
9284 randosSpy->setTrustedOverlay(true);
9285 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9286
9287 // The event is targeted at owner's window, so injection should succeed, but the spy should
9288 // not receive the event.
9289 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9290 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9291 randosSpy->assertNoEvents();
9292 window->consumeMotionDown();
9293}
9294
9295TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9296 auto owner = User(mDispatcher, 10, 11);
9297 auto window = owner.createWindow();
9298
9299 auto rando = User(mDispatcher, 20, 21);
9300 auto randosSpy = rando.createWindow();
9301 randosSpy->setSpy(true);
9302 randosSpy->setTrustedOverlay(true);
9303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9304
9305 // A user that has injection permission can inject into any window.
9306 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9307 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9308 ADISPLAY_ID_DEFAULT));
9309 randosSpy->consumeMotionDown();
9310 window->consumeMotionDown();
9311
9312 setFocusedWindow(randosSpy);
9313 randosSpy->consumeFocusEvent(true);
9314
9315 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9316 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9317 window->assertNoEvents();
9318}
9319
9320TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9321 auto owner = User(mDispatcher, 10, 11);
9322 auto window = owner.createWindow();
9323
9324 auto rando = User(mDispatcher, 20, 21);
9325 auto randosWindow = rando.createWindow();
9326 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9327 randosWindow->setWatchOutsideTouch(true);
9328 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9329
9330 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9331 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9332 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9333 window->consumeMotionDown();
9334 randosWindow->consumeMotionOutside();
9335}
9336
Garfield Tane84e6f92019-08-29 17:28:41 -07009337} // namespace android::inputdispatcher