blob: d419e5258763ae189070a9b6ad71253090f4325b [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080018
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070019#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080020#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080021#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070022#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070023#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000024#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080025#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080026#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100027#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080029#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100030
Garfield Tan1c7bc862020-01-28 13:24:04 -080031#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080032#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070033#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080034#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080035#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036
Garfield Tan1c7bc862020-01-28 13:24:04 -080037using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050038using android::gui::FocusRequest;
39using android::gui::TouchOcclusionMode;
40using android::gui::WindowInfo;
41using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080042using android::os::InputEventInjectionResult;
43using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080044
Garfield Tane84e6f92019-08-29 17:28:41 -070045namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Dominik Laskowski2f01d772022-03-23 16:01:29 -070047using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080048using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049
Michael Wrightd02c5b62014-02-10 15:10:22 -080050// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000051static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080052
53// An arbitrary device id.
Prabir Pradhan5735a322022-04-11 17:23:34 +000054static constexpr int32_t DEVICE_ID = 1;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080055static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080056
Jeff Brownf086ddb2014-02-11 14:28:48 -080057// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000058static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
59static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080060
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080061static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
62static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
63static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
64static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
65static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080066static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080067static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080068/**
69 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
70 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
71 * index 0) is the new pointer going down. The same pointer could have been placed at a different
72 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
73 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
74 * pointer id=0 leaves but the pointer id=1 remains.
75 */
76static constexpr int32_t POINTER_0_DOWN =
77 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080078static constexpr int32_t POINTER_1_DOWN =
79 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000080static constexpr int32_t POINTER_2_DOWN =
81 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000082static constexpr int32_t POINTER_3_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000084static constexpr int32_t POINTER_0_UP =
85 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080086static constexpr int32_t POINTER_1_UP =
87 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
88
Antonio Kantek15beb512022-06-13 22:35:41 +000089// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000090static constexpr int32_t WINDOW_PID = 999;
91static constexpr int32_t WINDOW_UID = 1001;
92
Antonio Kantek15beb512022-06-13 22:35:41 +000093// The default pid and uid for the windows created on the secondary display by the test.
94static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
95static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
96
Prabir Pradhan5735a322022-04-11 17:23:34 +000097// The default policy flags to use for event injection by tests.
98static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -080099
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000100// An arbitrary pid of the gesture monitor window
101static constexpr int32_t MONITOR_PID = 2001;
102
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800103static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
104
Arthur Hungc539dbb2022-12-08 07:45:36 +0000105static constexpr int expectedWallpaperFlags =
106 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
107
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800108using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
109
chaviwd1c23182019-12-20 18:44:56 -0800110struct PointF {
111 float x;
112 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800113 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800114};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800115
Gang Wang342c9272020-01-13 13:15:04 -0500116/**
117 * Return a DOWN key event with KEYCODE_A.
118 */
119static KeyEvent getTestKeyEvent() {
120 KeyEvent event;
121
Garfield Tanfbe732e2020-01-24 11:26:14 -0800122 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
123 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
124 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500125 return event;
126}
127
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000128static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
129 ASSERT_EQ(expectedAction, receivedAction)
130 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
131 << MotionEvent::actionToString(receivedAction);
132}
133
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800134MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
135 bool matches = action == arg.getAction();
136 if (!matches) {
137 *result_listener << "expected action " << MotionEvent::actionToString(action)
138 << ", but got " << MotionEvent::actionToString(arg.getAction());
139 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800140 if (action == AMOTION_EVENT_ACTION_DOWN) {
141 if (!matches) {
142 *result_listener << "; ";
143 }
144 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
145 matches &= arg.getDownTime() == arg.getEventTime();
146 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800147 if (action == AMOTION_EVENT_ACTION_CANCEL) {
148 if (!matches) {
149 *result_listener << "; ";
150 }
151 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
152 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
153 }
154 return matches;
155}
156
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800157MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
158 return arg.getDownTime() == downTime;
159}
160
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800161MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
162 return arg.getDisplayId() == displayId;
163}
164
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800165MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
166 return arg.getDeviceId() == deviceId;
167}
168
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800169MATCHER_P(WithSource, source, "InputEvent with specified source") {
170 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
171 << inputEventSourceToString(arg.getSource());
172 return arg.getSource() == source;
173}
174
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800175MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
176 return arg.getFlags() == flags;
177}
178
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800179MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
180 if (arg.getPointerCount() != 1) {
181 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
182 return false;
183 }
Harry Cutts33476232023-01-30 19:57:29 +0000184 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800185}
186
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800187MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
188 return arg.getPointerCount() == pointerCount;
189}
190
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800191MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
192 // Build a map for the received pointers, by pointer id
193 std::map<int32_t /*pointerId*/, PointF> actualPointers;
194 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
195 const int32_t pointerId = arg.getPointerId(pointerIndex);
196 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
197 }
198 return pointers == actualPointers;
199}
200
Michael Wrightd02c5b62014-02-10 15:10:22 -0800201// --- FakeInputDispatcherPolicy ---
202
203class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
204 InputDispatcherConfiguration mConfig;
205
Prabir Pradhanedd96402022-02-15 01:46:16 -0800206 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
207
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208protected:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000209 virtual ~FakeInputDispatcherPolicy() {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210
211public:
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000212 FakeInputDispatcherPolicy() {}
Jackal Guof9696682018-10-05 12:23:23 +0800213
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800214 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700215 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700216 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700217 EXPECT_EQ(event.getDisplayId(), args.displayId);
218
219 const auto& keyEvent = static_cast<const KeyEvent&>(event);
220 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
221 EXPECT_EQ(keyEvent.getAction(), args.action);
222 });
Jackal Guof9696682018-10-05 12:23:23 +0800223 }
224
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700225 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
226 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700227 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 EXPECT_EQ(event.getDisplayId(), args.displayId);
229
230 const auto& motionEvent = static_cast<const MotionEvent&>(event);
231 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
232 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000233 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
234 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
235 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
236 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700237 });
Jackal Guof9696682018-10-05 12:23:23 +0800238 }
239
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700240 void assertFilterInputEventWasNotCalled() {
241 std::scoped_lock lock(mLock);
242 ASSERT_EQ(nullptr, mFilteredEvent);
243 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800244
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800245 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700246 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800247 ASSERT_TRUE(mConfigurationChangedTime)
248 << "Timed out waiting for configuration changed call";
249 ASSERT_EQ(*mConfigurationChangedTime, when);
250 mConfigurationChangedTime = std::nullopt;
251 }
252
253 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700254 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800255 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800256 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800257 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
258 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
259 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
260 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
261 mLastNotifySwitch = std::nullopt;
262 }
263
chaviwfd6d3512019-03-25 13:23:49 -0700264 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700265 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800266 ASSERT_EQ(touchedToken, mOnPointerDownToken);
267 mOnPointerDownToken.clear();
268 }
269
270 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700271 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800272 ASSERT_TRUE(mOnPointerDownToken == nullptr)
273 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700274 }
275
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700276 // This function must be called soon after the expected ANR timer starts,
277 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500278 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700279 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500280 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 std::unique_lock lock(mLock);
282 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 ASSERT_NO_FATAL_FAILURE(
285 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700287 }
288
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000289 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 const sp<WindowInfoHandle>& window) {
291 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
292 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
293 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500294 }
295
Prabir Pradhanedd96402022-02-15 01:46:16 -0800296 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
297 const sp<IBinder>& expectedToken,
298 int32_t expectedPid) {
299 std::unique_lock lock(mLock);
300 android::base::ScopedLockAssertion assumeLocked(mLock);
301 AnrResult result;
302 ASSERT_NO_FATAL_FAILURE(result =
303 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
304 const auto& [token, pid] = result;
305 ASSERT_EQ(expectedToken, token);
306 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500307 }
308
Prabir Pradhanedd96402022-02-15 01:46:16 -0800309 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000310 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500311 std::unique_lock lock(mLock);
312 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800313 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
314 const auto& [token, _] = result;
315 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000316 }
317
Prabir Pradhanedd96402022-02-15 01:46:16 -0800318 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
319 int32_t expectedPid) {
320 std::unique_lock lock(mLock);
321 android::base::ScopedLockAssertion assumeLocked(mLock);
322 AnrResult result;
323 ASSERT_NO_FATAL_FAILURE(
324 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
325 const auto& [token, pid] = result;
326 ASSERT_EQ(expectedToken, token);
327 ASSERT_EQ(expectedPid, pid);
328 }
329
330 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000331 sp<IBinder> getResponsiveWindowToken() {
332 std::unique_lock lock(mLock);
333 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800334 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
335 const auto& [token, _] = result;
336 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700337 }
338
339 void assertNotifyAnrWasNotCalled() {
340 std::scoped_lock lock(mLock);
341 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800342 ASSERT_TRUE(mAnrWindows.empty());
343 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500344 << "ANR was not called, but please also consume the 'connection is responsive' "
345 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700346 }
347
Garfield Tan1c7bc862020-01-28 13:24:04 -0800348 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
349 mConfig.keyRepeatTimeout = timeout;
350 mConfig.keyRepeatDelay = delay;
351 }
352
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000353 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800354 std::unique_lock lock(mLock);
355 base::ScopedLockAssertion assumeLocked(mLock);
356
357 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
358 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000359 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800360 enabled;
361 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
363 << ") to be called.";
364 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800365 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000366 auto request = *mPointerCaptureRequest;
367 mPointerCaptureRequest.reset();
368 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800369 }
370
371 void assertSetPointerCaptureNotCalled() {
372 std::unique_lock lock(mLock);
373 base::ScopedLockAssertion assumeLocked(mLock);
374
375 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000376 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800377 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000378 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800379 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000380 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800381 }
382
arthurhungf452d0b2021-01-06 00:19:52 +0800383 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
384 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800385 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800386 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800387 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800388 }
389
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800390 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
391 std::unique_lock lock(mLock);
392 base::ScopedLockAssertion assumeLocked(mLock);
393 std::optional<sp<IBinder>> receivedToken =
394 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
395 mNotifyInputChannelBroken);
396 ASSERT_TRUE(receivedToken.has_value());
397 ASSERT_EQ(token, *receivedToken);
398 }
399
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800400 /**
401 * Set policy timeout. A value of zero means next key will not be intercepted.
402 */
403 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
404 mInterceptKeyTimeout = timeout;
405 }
406
Josep del Riob3981622023-04-18 15:49:45 +0000407 void assertUserActivityPoked() {
408 std::scoped_lock lock(mLock);
409 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
410 }
411
412 void assertUserActivityNotPoked() {
413 std::scoped_lock lock(mLock);
414 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
415 }
416
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700418 std::mutex mLock;
419 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
420 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
421 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
422 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800423
Prabir Pradhan99987712020-11-10 18:43:05 -0800424 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000425
426 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800427
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700428 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700429 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800430 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
431 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700432 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800433 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
434 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700435
arthurhungf452d0b2021-01-06 00:19:52 +0800436 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800437 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000438 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800439
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800440 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
441
Prabir Pradhanedd96402022-02-15 01:46:16 -0800442 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
443 // for a specific container to become non-empty. When the container is non-empty, return the
444 // first entry from the container and erase it.
445 template <class T>
446 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
447 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
448 // If there is an ANR, Dispatcher won't be idle because there are still events
449 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
450 // before checking if ANR was called.
451 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
452 // to provide it some time to act. 100ms seems reasonable.
453 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
454 const std::chrono::time_point start = std::chrono::steady_clock::now();
455 std::optional<T> token =
456 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
457 if (!token.has_value()) {
458 ADD_FAILURE() << "Did not receive the ANR callback";
459 return {};
460 }
461
462 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
463 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
464 // the dispatcher started counting before this function was called
465 if (std::chrono::abs(timeout - waited) > 100ms) {
466 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
467 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
468 << "ms, but waited "
469 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
470 << "ms instead";
471 }
472 return *token;
473 }
474
475 template <class T>
476 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
477 std::queue<T>& storage,
478 std::unique_lock<std::mutex>& lock,
479 std::condition_variable& condition)
480 REQUIRES(mLock) {
481 condition.wait_for(lock, timeout,
482 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
483 if (storage.empty()) {
484 ADD_FAILURE() << "Did not receive the expected callback";
485 return std::nullopt;
486 }
487 T item = storage.front();
488 storage.pop();
489 return std::make_optional(item);
490 }
491
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600492 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700493 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800494 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800495 }
496
Prabir Pradhanedd96402022-02-15 01:46:16 -0800497 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
498 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700499 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800500 ASSERT_TRUE(pid.has_value());
501 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700502 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500503 }
504
Prabir Pradhanedd96402022-02-15 01:46:16 -0800505 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
506 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500507 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800508 ASSERT_TRUE(pid.has_value());
509 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500510 mNotifyAnr.notify_all();
511 }
512
513 void notifyNoFocusedWindowAnr(
514 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
515 std::scoped_lock lock(mLock);
516 mAnrApplications.push(applicationHandle);
517 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800518 }
519
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800520 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
521 std::scoped_lock lock(mLock);
522 mBrokenInputChannels.push(connectionToken);
523 mNotifyInputChannelBroken.notify_all();
524 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800525
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600526 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700527
Chris Yef59a2f42020-10-16 12:55:26 -0700528 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
529 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
530 const std::vector<float>& values) override {}
531
532 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
533 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000534
Chris Yefb552902021-02-03 17:18:37 -0800535 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
536
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600537 void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538 *outConfig = mConfig;
539 }
540
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600541 bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700542 std::scoped_lock lock(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800543 switch (inputEvent->getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700544 case InputEventType::KEY: {
Jackal Guof9696682018-10-05 12:23:23 +0800545 const KeyEvent* keyEvent = static_cast<const KeyEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800546 mFilteredEvent = std::make_unique<KeyEvent>(*keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800547 break;
548 }
549
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700550 case InputEventType::MOTION: {
Jackal Guof9696682018-10-05 12:23:23 +0800551 const MotionEvent* motionEvent = static_cast<const MotionEvent*>(inputEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800552 mFilteredEvent = std::make_unique<MotionEvent>(*motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800553 break;
554 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 default: {
556 ADD_FAILURE() << "Should only filter keys or motions";
557 break;
558 }
Jackal Guof9696682018-10-05 12:23:23 +0800559 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800560 return true;
561 }
562
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800563 void interceptKeyBeforeQueueing(const KeyEvent* inputEvent, uint32_t&) override {
564 if (inputEvent->getAction() == AKEY_EVENT_ACTION_UP) {
565 // Clear intercept state when we handled the event.
566 mInterceptKeyTimeout = 0ms;
567 }
568 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800569
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600570 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800571
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600572 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent*, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800573 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
574 // Clear intercept state so we could dispatch the event in next wake.
575 mInterceptKeyTimeout = 0ms;
576 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800577 }
578
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600579 bool dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent*, uint32_t, KeyEvent*) override {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580 return false;
581 }
582
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600583 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
584 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700585 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800586 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
587 * essentially a passthrough for notifySwitch.
588 */
Harry Cutts33476232023-01-30 19:57:29 +0000589 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800590 }
591
Josep del Riob3981622023-04-18 15:49:45 +0000592 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
593 std::scoped_lock lock(mLock);
594 mPokedUserActivity = true;
595 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600597 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700598 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700599 mOnPointerDownToken = newToken;
600 }
601
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000602 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800603 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000604 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800605 mPointerCaptureChangedCondition.notify_all();
606 }
607
arthurhungf452d0b2021-01-06 00:19:52 +0800608 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
609 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800610 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800611 mDropTargetWindowToken = token;
612 }
613
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700614 void assertFilterInputEventWasCalledInternal(
615 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700616 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800617 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700618 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800619 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800620 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800621};
622
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623// --- InputDispatcherTest ---
624
625class InputDispatcherTest : public testing::Test {
626protected:
627 sp<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700628 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000630 void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700631 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800632 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800633 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000634 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700635 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800636 }
637
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000638 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700639 ASSERT_EQ(OK, mDispatcher->stop());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640 mFakePolicy.clear();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700641 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800642 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700643
644 /**
645 * Used for debugging when writing the test
646 */
647 void dumpDispatcherState() {
648 std::string dump;
649 mDispatcher->dump(dump);
650 std::stringstream ss(dump);
651 std::string to;
652
653 while (std::getline(ss, to, '\n')) {
654 ALOGE("%s", to.c_str());
655 }
656 }
Vishnu Nair958da932020-08-21 17:12:37 -0700657
Chavi Weingarten847e8512023-03-29 00:26:09 +0000658 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700659 FocusRequest request;
660 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000661 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700662 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
663 request.displayId = window->getInfo()->displayId;
664 mDispatcher->setFocusedWindow(request);
665 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800666};
667
Michael Wrightd02c5b62014-02-10 15:10:22 -0800668TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
669 KeyEvent event;
670
671 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800672 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
673 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600674 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
675 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800676 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000677 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000678 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679 << "Should reject key events with undefined action.";
680
681 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800682 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
683 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600684 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800685 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000686 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000687 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800688 << "Should reject key events with ACTION_MULTIPLE.";
689}
690
691TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
692 MotionEvent event;
693 PointerProperties pointerProperties[MAX_POINTERS + 1];
694 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800695 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800696 pointerProperties[i].clear();
697 pointerProperties[i].id = i;
698 pointerCoords[i].clear();
699 }
700
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800701 // Some constants commonly used below
702 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
703 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
704 constexpr int32_t metaState = AMETA_NONE;
705 constexpr MotionClassification classification = MotionClassification::NONE;
706
chaviw9eaa22c2020-07-01 16:21:27 -0700707 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800708 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800709 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700710 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
711 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700712 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
713 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700714 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800715 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000716 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000717 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718 << "Should reject motion events with undefined action.";
719
720 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800721 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800722 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
723 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
724 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
725 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500726 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800727 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000728 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000729 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800730 << "Should reject motion events with pointer down index too large.";
731
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700733 AMOTION_EVENT_ACTION_POINTER_DOWN |
734 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700735 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
736 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700737 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500738 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000740 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000741 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800742 << "Should reject motion events with pointer down index too small.";
743
744 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800745 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800746 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
747 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
748 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
749 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500750 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800751 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000752 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000753 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800754 << "Should reject motion events with pointer up index too large.";
755
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700757 AMOTION_EVENT_ACTION_POINTER_UP |
758 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700759 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
760 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700761 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500762 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800763 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000764 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000765 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800766 << "Should reject motion events with pointer up index too small.";
767
768 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
770 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700771 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
773 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700774 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800775 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000776 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000777 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800778 << "Should reject motion events with 0 pointers.";
779
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700785 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with more than MAX_POINTERS pointers.";
790
791 // Rejects motion events with invalid pointer ids.
792 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800793 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
794 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700795 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700796 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
797 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700798 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800799 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000800 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000801 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800802 << "Should reject motion events with pointer ids less than 0.";
803
804 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800805 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
806 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700807 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700808 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
809 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700810 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800811 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000812 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000813 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800814 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
815
816 // Rejects motion events with duplicate pointer ids.
817 pointerProperties[0].id = 1;
818 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800819 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
820 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700821 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700822 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
823 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700824 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800825 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000826 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000827 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800828 << "Should reject motion events with duplicate pointer ids.";
829}
830
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800831/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
832
833TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
834 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000835 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800836 ASSERT_TRUE(mDispatcher->waitForIdle());
837
838 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
839}
840
841TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000842 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
843 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000844 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800845
846 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
847 args.policyFlags |= POLICY_FLAG_TRUSTED;
848 mFakePolicy->assertNotifySwitchWasCalled(args);
849}
850
Arthur Hungb92218b2018-08-14 12:00:21 +0800851// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700852static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700853// Default input dispatching timeout if there is no focused application or paused window
854// from which to determine an appropriate dispatching timeout.
855static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
856 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
857 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800858
859class FakeApplicationHandle : public InputApplicationHandle {
860public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861 FakeApplicationHandle() {
862 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700863 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500864 mInfo.dispatchingTimeoutMillis =
865 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700866 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800867 virtual ~FakeApplicationHandle() {}
868
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000869 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700870
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500871 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
872 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700873 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800874};
875
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800876class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800877public:
Garfield Tan15601662020-09-22 15:32:38 -0700878 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800879 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700880 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800881 }
882
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800883 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700884 InputEvent* event;
885 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
886 if (!consumeSeq) {
887 return nullptr;
888 }
889 finishEvent(*consumeSeq);
890 return event;
891 }
892
893 /**
894 * Receive an event without acknowledging it.
895 * Return the sequence number that could later be used to send finished signal.
896 */
897 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800898 uint32_t consumeSeq;
899 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800900
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800901 std::chrono::time_point start = std::chrono::steady_clock::now();
902 status_t status = WOULD_BLOCK;
903 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000904 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 &event);
906 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
907 if (elapsed > 100ms) {
908 break;
909 }
910 }
911
912 if (status == WOULD_BLOCK) {
913 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 }
916
917 if (status != OK) {
918 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700919 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 }
921 if (event == nullptr) {
922 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700925 if (outEvent != nullptr) {
926 *outEvent = event;
927 }
928 return consumeSeq;
929 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700931 /**
932 * To be used together with "receiveEvent" to complete the consumption of an event.
933 */
934 void finishEvent(uint32_t consumeSeq) {
935 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
936 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
938
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000939 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
940 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
941 ASSERT_EQ(OK, status);
942 }
943
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700944 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000945 std::optional<int32_t> expectedDisplayId,
946 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 InputEvent* event = consume();
948
949 ASSERT_NE(nullptr, event) << mName.c_str()
950 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800951 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700952 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
953 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800954
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000955 if (expectedDisplayId.has_value()) {
956 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
957 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800958
Tiger Huang8664f8c2018-10-11 19:14:35 +0800959 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700960 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800961 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
962 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963 if (expectedFlags.has_value()) {
964 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
965 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800966 break;
967 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700968 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800969 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000970 assertMotionAction(expectedAction, motionEvent.getAction());
971
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000972 if (expectedFlags.has_value()) {
973 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
974 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800975 break;
976 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100978 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
979 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800981 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
982 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700983 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000984 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
985 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700986 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800987 FAIL() << "Use 'consumeDragEvent' for DRAG events";
988 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800989 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800990 }
991
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800992 MotionEvent* consumeMotion() {
993 InputEvent* event = consume();
994
995 if (event == nullptr) {
996 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
997 return nullptr;
998 }
999
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 if (event->getType() != InputEventType::MOTION) {
1001 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001002 return nullptr;
1003 }
1004 return static_cast<MotionEvent*>(event);
1005 }
1006
1007 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1008 MotionEvent* motionEvent = consumeMotion();
1009 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1010 ASSERT_THAT(*motionEvent, matcher);
1011 }
1012
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001013 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1014 InputEvent* event = consume();
1015 ASSERT_NE(nullptr, event) << mName.c_str()
1016 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001017 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1018 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001019
1020 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1021 << mName.c_str() << ": event displayId should always be NONE.";
1022
1023 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1024 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001025 }
1026
Prabir Pradhan99987712020-11-10 18:43:05 -08001027 void consumeCaptureEvent(bool hasCapture) {
1028 const InputEvent* event = consume();
1029 ASSERT_NE(nullptr, event) << mName.c_str()
1030 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001031 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1032 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001033
1034 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1035 << mName.c_str() << ": event displayId should always be NONE.";
1036
1037 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1038 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1039 }
1040
arthurhungb89ccb02020-12-30 16:19:01 +08001041 void consumeDragEvent(bool isExiting, float x, float y) {
1042 const InputEvent* event = consume();
1043 ASSERT_NE(nullptr, event) << mName.c_str()
1044 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001045 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001046
1047 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
1050 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1051 EXPECT_EQ(isExiting, dragEvent.isExiting());
1052 EXPECT_EQ(x, dragEvent.getX());
1053 EXPECT_EQ(y, dragEvent.getY());
1054 }
1055
Antonio Kantekf16f2832021-09-28 04:39:20 +00001056 void consumeTouchModeEvent(bool inTouchMode) {
1057 const InputEvent* event = consume();
1058 ASSERT_NE(nullptr, event) << mName.c_str()
1059 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001060 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1061 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001062
1063 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1064 << mName.c_str() << ": event displayId should always be NONE.";
1065 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1066 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1067 }
1068
chaviwd1c23182019-12-20 18:44:56 -08001069 void assertNoEvents() {
1070 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001071 if (event == nullptr) {
1072 return;
1073 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001074 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001075 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1076 ADD_FAILURE() << "Received key event "
1077 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001078 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001079 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1080 ADD_FAILURE() << "Received motion event "
1081 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001082 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001083 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1084 ADD_FAILURE() << "Received focus event, hasFocus = "
1085 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001086 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001087 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1088 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1089 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001090 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001091 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1092 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1093 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 }
1095 FAIL() << mName.c_str()
1096 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001097 }
1098
1099 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1100
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001101 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1102
chaviwd1c23182019-12-20 18:44:56 -08001103protected:
1104 std::unique_ptr<InputConsumer> mConsumer;
1105 PreallocatedInputEventFactory mEventFactory;
1106
1107 std::string mName;
1108};
1109
chaviw3277faf2021-05-19 16:45:23 -05001110class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001111public:
1112 static const int32_t WIDTH = 600;
1113 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001114
Chris Yea209fde2020-07-22 13:54:51 -07001115 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001116 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001117 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001118 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001119 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001120 base::Result<std::unique_ptr<InputChannel>> channel =
1121 dispatcher->createInputChannel(name);
1122 token = (*channel)->getConnectionToken();
1123 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001124 }
1125
1126 inputApplicationHandle->updateInfo();
1127 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1128
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001129 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001130 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001131 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001132 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001133 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001134 mInfo.frameLeft = 0;
1135 mInfo.frameTop = 0;
1136 mInfo.frameRight = WIDTH;
1137 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001138 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001139 mInfo.globalScaleFactor = 1.0;
1140 mInfo.touchableRegion.clear();
1141 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001142 mInfo.ownerPid = WINDOW_PID;
1143 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001145 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001146 }
1147
Arthur Hungabbb9d82021-09-01 14:52:30 +00001148 sp<FakeWindowHandle> clone(
1149 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001150 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001151 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001152 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1153 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001154 return handle;
1155 }
1156
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001157 void setTouchable(bool touchable) {
1158 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1159 }
chaviwd1c23182019-12-20 18:44:56 -08001160
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001161 void setFocusable(bool focusable) {
1162 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1163 }
1164
1165 void setVisible(bool visible) {
1166 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1167 }
Vishnu Nair958da932020-08-21 17:12:37 -07001168
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001169 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001170 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001171 }
1172
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001173 void setPaused(bool paused) {
1174 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1175 }
1176
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001177 void setPreventSplitting(bool preventSplitting) {
1178 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001179 }
1180
1181 void setSlippery(bool slippery) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1183 }
1184
1185 void setWatchOutsideTouch(bool watchOutside) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1187 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001188
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001189 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1190
1191 void setInterceptsStylus(bool interceptsStylus) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1193 }
1194
1195 void setDropInput(bool dropInput) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1197 }
1198
1199 void setDropInputIfObscured(bool dropInputIfObscured) {
1200 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1201 }
1202
1203 void setNoInputChannel(bool noInputChannel) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1205 }
1206
Josep del Riob3981622023-04-18 15:49:45 +00001207 void setDisableUserActivity(bool disableUserActivity) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1209 }
1210
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001211 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1212
chaviw3277faf2021-05-19 16:45:23 -05001213 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001214
Bernardo Rufino7393d172021-02-26 13:56:11 +00001215 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1216
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001217 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001218 mInfo.frameLeft = frame.left;
1219 mInfo.frameTop = frame.top;
1220 mInfo.frameRight = frame.right;
1221 mInfo.frameBottom = frame.bottom;
1222 mInfo.touchableRegion.clear();
1223 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001224
1225 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1226 ui::Transform translate;
1227 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1228 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001229 }
1230
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001231 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1232
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001233 void setIsWallpaper(bool isWallpaper) {
1234 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1235 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001236
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001237 void setDupTouchToWallpaper(bool hasWallpaper) {
1238 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1239 }
chaviwd1c23182019-12-20 18:44:56 -08001240
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001241 void setTrustedOverlay(bool trustedOverlay) {
1242 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1243 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001244
chaviw9eaa22c2020-07-01 16:21:27 -07001245 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1246 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1247 }
1248
1249 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001250
yunho.shinf4a80b82020-11-16 21:13:57 +09001251 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1252
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001253 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001254 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001255 }
1256
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001257 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001258 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001259 }
1260
Svet Ganov5d3bc372020-01-26 23:11:07 -08001261 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001262 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001263 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1264 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001265 }
1266
1267 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001268 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001269 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1270 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001271 }
1272
1273 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001274 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001275 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1276 }
1277
1278 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1279 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001280 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001281 expectedFlags);
1282 }
1283
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001285 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1286 int32_t expectedFlags = 0) {
1287 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1288 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001289 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001290 }
1291
1292 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedFlags = 0) {
1294 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1295 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001296 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 }
1298
1299 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001301 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001302 expectedFlags);
1303 }
1304
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001305 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1306 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001307 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001308 expectedFlags);
1309 }
1310
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001311 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1312 int32_t expectedFlags = 0) {
1313 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001314 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001315 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001316 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1317 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1318 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1319 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1320 }
1321
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001322 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1323 ASSERT_NE(mInputReceiver, nullptr)
1324 << "Cannot consume events from a window with no receiver";
1325 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1326 }
1327
Prabir Pradhan99987712020-11-10 18:43:05 -08001328 void consumeCaptureEvent(bool hasCapture) {
1329 ASSERT_NE(mInputReceiver, nullptr)
1330 << "Cannot consume events from a window with no receiver";
1331 mInputReceiver->consumeCaptureEvent(hasCapture);
1332 }
1333
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001334 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1335 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001336 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001337 ASSERT_THAT(*motionEvent, matcher);
1338 }
1339
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001340 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001341 std::optional<int32_t> expectedDisplayId,
1342 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001343 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1344 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1345 expectedFlags);
1346 }
1347
arthurhungb89ccb02020-12-30 16:19:01 +08001348 void consumeDragEvent(bool isExiting, float x, float y) {
1349 mInputReceiver->consumeDragEvent(isExiting, x, y);
1350 }
1351
Antonio Kantekf16f2832021-09-28 04:39:20 +00001352 void consumeTouchModeEvent(bool inTouchMode) {
1353 ASSERT_NE(mInputReceiver, nullptr)
1354 << "Cannot consume events from a window with no receiver";
1355 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1356 }
1357
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001358 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001359 if (mInputReceiver == nullptr) {
1360 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1361 return std::nullopt;
1362 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001363 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001364 }
1365
1366 void finishEvent(uint32_t sequenceNum) {
1367 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1368 mInputReceiver->finishEvent(sequenceNum);
1369 }
1370
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001371 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1372 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1373 mInputReceiver->sendTimeline(inputEventId, timeline);
1374 }
1375
chaviwaf87b3e2019-10-01 16:59:28 -07001376 InputEvent* consume() {
1377 if (mInputReceiver == nullptr) {
1378 return nullptr;
1379 }
1380 return mInputReceiver->consume();
1381 }
1382
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001383 MotionEvent* consumeMotion() {
1384 InputEvent* event = consume();
1385 if (event == nullptr) {
1386 ADD_FAILURE() << "Consume failed : no event";
1387 return nullptr;
1388 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001389 if (event->getType() != InputEventType::MOTION) {
1390 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001391 return nullptr;
1392 }
1393 return static_cast<MotionEvent*>(event);
1394 }
1395
Arthur Hungb92218b2018-08-14 12:00:21 +08001396 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001397 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001398 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001399 return; // Can't receive events if the window does not have input channel
1400 }
1401 ASSERT_NE(nullptr, mInputReceiver)
1402 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001403 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001404 }
1405
chaviwaf87b3e2019-10-01 16:59:28 -07001406 sp<IBinder> getToken() { return mInfo.token; }
1407
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001408 const std::string& getName() { return mName; }
1409
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001410 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1411 mInfo.ownerPid = ownerPid;
1412 mInfo.ownerUid = ownerUid;
1413 }
1414
Prabir Pradhanedd96402022-02-15 01:46:16 -08001415 int32_t getPid() const { return mInfo.ownerPid; }
1416
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001417 void destroyReceiver() { mInputReceiver = nullptr; }
1418
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001419 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1420
chaviwd1c23182019-12-20 18:44:56 -08001421private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001422 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001423 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001424 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001425};
1426
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001427std::atomic<int32_t> FakeWindowHandle::sId{1};
1428
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001429static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001430 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001431 int32_t displayId = ADISPLAY_ID_NONE,
1432 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001433 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001434 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1435 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001436 KeyEvent event;
1437 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1438
1439 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001440 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001441 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1442 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001443
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001444 if (!allowKeyRepeat) {
1445 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1446 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001447 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001448 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001449}
1450
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001451static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001452 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001453 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001454}
1455
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001456// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1457// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1458// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001459static InputEventInjectionResult injectKeyDownNoRepeat(
1460 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001461 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001462 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001463 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001464}
1465
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001466static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001467 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001468 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001469}
1470
Garfield Tandf26e862020-07-01 20:18:19 -07001471class PointerBuilder {
1472public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001473 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001474 mProperties.clear();
1475 mProperties.id = id;
1476 mProperties.toolType = toolType;
1477 mCoords.clear();
1478 }
1479
1480 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1481
1482 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1483
1484 PointerBuilder& axis(int32_t axis, float value) {
1485 mCoords.setAxisValue(axis, value);
1486 return *this;
1487 }
1488
1489 PointerProperties buildProperties() const { return mProperties; }
1490
1491 PointerCoords buildCoords() const { return mCoords; }
1492
1493private:
1494 PointerProperties mProperties;
1495 PointerCoords mCoords;
1496};
1497
1498class MotionEventBuilder {
1499public:
1500 MotionEventBuilder(int32_t action, int32_t source) {
1501 mAction = action;
1502 mSource = source;
1503 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001504 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001505 }
1506
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001507 MotionEventBuilder& deviceId(int32_t deviceId) {
1508 mDeviceId = deviceId;
1509 return *this;
1510 }
1511
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001512 MotionEventBuilder& downTime(nsecs_t downTime) {
1513 mDownTime = downTime;
1514 return *this;
1515 }
1516
Garfield Tandf26e862020-07-01 20:18:19 -07001517 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1518 mEventTime = eventTime;
1519 return *this;
1520 }
1521
1522 MotionEventBuilder& displayId(int32_t displayId) {
1523 mDisplayId = displayId;
1524 return *this;
1525 }
1526
1527 MotionEventBuilder& actionButton(int32_t actionButton) {
1528 mActionButton = actionButton;
1529 return *this;
1530 }
1531
arthurhung6d4bed92021-03-17 11:59:33 +08001532 MotionEventBuilder& buttonState(int32_t buttonState) {
1533 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001534 return *this;
1535 }
1536
1537 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1538 mRawXCursorPosition = rawXCursorPosition;
1539 return *this;
1540 }
1541
1542 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1543 mRawYCursorPosition = rawYCursorPosition;
1544 return *this;
1545 }
1546
1547 MotionEventBuilder& pointer(PointerBuilder pointer) {
1548 mPointers.push_back(pointer);
1549 return *this;
1550 }
1551
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001552 MotionEventBuilder& addFlag(uint32_t flags) {
1553 mFlags |= flags;
1554 return *this;
1555 }
1556
Garfield Tandf26e862020-07-01 20:18:19 -07001557 MotionEvent build() {
1558 std::vector<PointerProperties> pointerProperties;
1559 std::vector<PointerCoords> pointerCoords;
1560 for (const PointerBuilder& pointer : mPointers) {
1561 pointerProperties.push_back(pointer.buildProperties());
1562 pointerCoords.push_back(pointer.buildCoords());
1563 }
1564
1565 // Set mouse cursor position for the most common cases to avoid boilerplate.
1566 if (mSource == AINPUT_SOURCE_MOUSE &&
1567 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1568 mPointers.size() == 1) {
1569 mRawXCursorPosition = pointerCoords[0].getX();
1570 mRawYCursorPosition = pointerCoords[0].getY();
1571 }
1572
1573 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001574 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001575 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001576 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001577 mButtonState, MotionClassification::NONE, identityTransform,
1578 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001579 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001580 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001581
1582 return event;
1583 }
1584
1585private:
1586 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001587 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001588 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001589 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001590 nsecs_t mEventTime;
1591 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1592 int32_t mActionButton{0};
1593 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001594 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001595 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1596 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1597
1598 std::vector<PointerBuilder> mPointers;
1599};
1600
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001601class MotionArgsBuilder {
1602public:
1603 MotionArgsBuilder(int32_t action, int32_t source) {
1604 mAction = action;
1605 mSource = source;
1606 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1607 mDownTime = mEventTime;
1608 }
1609
1610 MotionArgsBuilder& deviceId(int32_t deviceId) {
1611 mDeviceId = deviceId;
1612 return *this;
1613 }
1614
1615 MotionArgsBuilder& downTime(nsecs_t downTime) {
1616 mDownTime = downTime;
1617 return *this;
1618 }
1619
1620 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1621 mEventTime = eventTime;
1622 return *this;
1623 }
1624
1625 MotionArgsBuilder& displayId(int32_t displayId) {
1626 mDisplayId = displayId;
1627 return *this;
1628 }
1629
1630 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1631 mPolicyFlags = policyFlags;
1632 return *this;
1633 }
1634
1635 MotionArgsBuilder& actionButton(int32_t actionButton) {
1636 mActionButton = actionButton;
1637 return *this;
1638 }
1639
1640 MotionArgsBuilder& buttonState(int32_t buttonState) {
1641 mButtonState = buttonState;
1642 return *this;
1643 }
1644
1645 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1646 mRawXCursorPosition = rawXCursorPosition;
1647 return *this;
1648 }
1649
1650 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1651 mRawYCursorPosition = rawYCursorPosition;
1652 return *this;
1653 }
1654
1655 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1656 mPointers.push_back(pointer);
1657 return *this;
1658 }
1659
1660 MotionArgsBuilder& addFlag(uint32_t flags) {
1661 mFlags |= flags;
1662 return *this;
1663 }
1664
1665 NotifyMotionArgs build() {
1666 std::vector<PointerProperties> pointerProperties;
1667 std::vector<PointerCoords> pointerCoords;
1668 for (const PointerBuilder& pointer : mPointers) {
1669 pointerProperties.push_back(pointer.buildProperties());
1670 pointerCoords.push_back(pointer.buildCoords());
1671 }
1672
1673 // Set mouse cursor position for the most common cases to avoid boilerplate.
1674 if (mSource == AINPUT_SOURCE_MOUSE &&
1675 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition) &&
1676 mPointers.size() == 1) {
1677 mRawXCursorPosition = pointerCoords[0].getX();
1678 mRawYCursorPosition = pointerCoords[0].getY();
1679 }
1680
1681 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1682 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
1683 AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
1684 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1685 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1686 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1687
1688 return args;
1689 }
1690
1691private:
1692 int32_t mAction;
1693 int32_t mDeviceId = DEVICE_ID;
1694 int32_t mSource;
1695 nsecs_t mDownTime;
1696 nsecs_t mEventTime;
1697 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1698 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1699 int32_t mActionButton{0};
1700 int32_t mButtonState{0};
1701 int32_t mFlags{0};
1702 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1703 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1704
1705 std::vector<PointerBuilder> mPointers;
1706};
1707
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001708static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001709 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001710 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001711 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1712 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1713 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1714 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001715}
1716
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001717static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001718 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001719 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001720 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001721 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1722 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001723 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001724 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1725 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Garfield Tandf26e862020-07-01 20:18:19 -07001726 MotionEvent event = MotionEventBuilder(action, source)
1727 .displayId(displayId)
1728 .eventTime(eventTime)
1729 .rawXCursorPosition(cursorPosition.x)
1730 .rawYCursorPosition(cursorPosition.y)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001731 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Garfield Tandf26e862020-07-01 20:18:19 -07001732 .x(position.x)
1733 .y(position.y))
1734 .build();
Arthur Hungb92218b2018-08-14 12:00:21 +08001735
1736 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001737 return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
1738 policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001739}
1740
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001741static InputEventInjectionResult injectMotionDown(
1742 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1743 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001744 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001745}
1746
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001747static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001748 int32_t source, int32_t displayId,
1749 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001750 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001751}
1752
Jackal Guof9696682018-10-05 12:23:23 +08001753static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1754 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1755 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001756 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001757 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1758 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001759
1760 return args;
1761}
1762
Josep del Riob3981622023-04-18 15:49:45 +00001763static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1764 int32_t displayId = ADISPLAY_ID_NONE) {
1765 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1766 // Define a valid key event.
1767 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1768 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1769 currentTime);
1770
1771 return args;
1772}
1773
1774static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1775 int32_t displayId = ADISPLAY_ID_NONE) {
1776 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1777 // Define a valid key event.
1778 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1779 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1780 AMETA_NONE, currentTime);
1781
1782 return args;
1783}
1784
Prabir Pradhan678438e2023-04-13 19:32:51 +00001785[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1786 int32_t displayId,
1787 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001788 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001789 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1790 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1791 }
1792
chaviwd1c23182019-12-20 18:44:56 -08001793 PointerProperties pointerProperties[pointerCount];
1794 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001795
chaviwd1c23182019-12-20 18:44:56 -08001796 for (size_t i = 0; i < pointerCount; i++) {
1797 pointerProperties[i].clear();
1798 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001799 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001800
chaviwd1c23182019-12-20 18:44:56 -08001801 pointerCoords[i].clear();
1802 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1803 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1804 }
Jackal Guof9696682018-10-05 12:23:23 +08001805
1806 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1807 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001808 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001809 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1810 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001811 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1812 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001813 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1814 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001815
1816 return args;
1817}
1818
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001819static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1820 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1821}
1822
chaviwd1c23182019-12-20 18:44:56 -08001823static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1824 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1825}
1826
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001827static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1828 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001829 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001830}
1831
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001832/**
1833 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1834 * broken channel.
1835 */
1836TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1837 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1838 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001839 sp<FakeWindowHandle>::make(application, mDispatcher,
1840 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001841
1842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1843
1844 // Window closes its channel, but the window remains.
1845 window->destroyReceiver();
1846 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1847}
1848
Arthur Hungb92218b2018-08-14 12:00:21 +08001849TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001850 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1852 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001853
Arthur Hung72d8dc32020-03-28 00:48:39 +00001854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1856 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001858
1859 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001860 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001861}
1862
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001863TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001865 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1866 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001867
1868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1869 // Inject a MotionEvent to an unknown display.
1870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1871 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1872 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1873
1874 // Window should receive motion event.
1875 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1876}
1877
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001878/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001879 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001880 * This test serves as a sanity check for the next test, where setInputWindows is
1881 * called twice.
1882 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001883TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001885 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1886 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001887 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001888
1889 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001891 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1892 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001894
1895 // Window should receive motion event.
1896 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1897}
1898
1899/**
1900 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001901 */
1902TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001904 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1905 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001906 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001907
1908 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1909 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001911 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1912 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001914
1915 // Window should receive motion event.
1916 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1917}
1918
Arthur Hungb92218b2018-08-14 12:00:21 +08001919// The foreground window should receive the first touch down event.
1920TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001921 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001922 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001923 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001924 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001925 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001926
Arthur Hung72d8dc32020-03-28 00:48:39 +00001927 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1929 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001931
1932 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001933 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001934 windowSecond->assertNoEvents();
1935}
1936
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001937/**
1938 * Two windows: A top window, and a wallpaper behind the window.
1939 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1940 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001941 * 1. foregroundWindow <-- dup touch to wallpaper
1942 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943 */
1944TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1946 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001948 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001949 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001950 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001951 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001952
1953 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1955 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1956 {100, 200}))
1957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1958
1959 // Both foreground window and its wallpaper should receive the touch down
1960 foregroundWindow->consumeMotionDown();
1961 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1962
1963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1964 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1965 ADISPLAY_ID_DEFAULT, {110, 200}))
1966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1967
1968 foregroundWindow->consumeMotionMove();
1969 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1970
1971 // Now the foreground window goes away, but the wallpaper stays
1972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1973 foregroundWindow->consumeMotionCancel();
1974 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1975 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1976}
1977
1978/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001979 * Two fingers down on the window, and lift off the first finger.
1980 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1981 * contains a single pointer.
1982 */
1983TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1984 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1985 sp<FakeWindowHandle> window =
1986 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1987
1988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001989 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1991 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1992 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001993 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001994 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1995 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1996 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1997 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001998 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001999 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2000 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2001 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
2002 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002003 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2004 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2005 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2006
2007 // Remove the window. The gesture should be canceled
2008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2009 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
2010 window->consumeMotionEvent(
2011 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
2012}
2013
2014/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002015 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
2016 * with the following differences:
2017 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
2018 * clean up the connection.
2019 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
2020 * Ensure that there's no crash in the dispatcher.
2021 */
2022TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
2023 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2024 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002025 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002026 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002027 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002028 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002029 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002030
2031 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2033 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2034 {100, 200}))
2035 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2036
2037 // Both foreground window and its wallpaper should receive the touch down
2038 foregroundWindow->consumeMotionDown();
2039 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2040
2041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2042 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2043 ADISPLAY_ID_DEFAULT, {110, 200}))
2044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2045
2046 foregroundWindow->consumeMotionMove();
2047 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2048
2049 // Wallpaper closes its channel, but the window remains.
2050 wallpaperWindow->destroyReceiver();
2051 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2052
2053 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2054 // is no longer valid.
2055 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2056 foregroundWindow->consumeMotionCancel();
2057}
2058
Arthur Hungc539dbb2022-12-08 07:45:36 +00002059class ShouldSplitTouchFixture : public InputDispatcherTest,
2060 public ::testing::WithParamInterface<bool> {};
2061INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2062 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002063/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002064 * A single window that receives touch (on top), and a wallpaper window underneath it.
2065 * The top window gets a multitouch gesture.
2066 * Ensure that wallpaper gets the same gesture.
2067 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002070 sp<FakeWindowHandle> foregroundWindow =
2071 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2072 foregroundWindow->setDupTouchToWallpaper(true);
2073 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002074
2075 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002076 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002077 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078
Arthur Hungc539dbb2022-12-08 07:45:36 +00002079 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002080
2081 // Touch down on top window
2082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2083 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2084 {100, 100}))
2085 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2086
2087 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002088 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002089 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2090
2091 // Second finger down on the top window
2092 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002093 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002095 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2096 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002097 .build();
2098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2099 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2100 InputEventInjectionSync::WAIT_FOR_RESULT))
2101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2102
Harry Cutts33476232023-01-30 19:57:29 +00002103 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2104 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002105 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002106
2107 const MotionEvent secondFingerUpEvent =
2108 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2109 .displayId(ADISPLAY_ID_DEFAULT)
2110 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002111 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2112 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002113 .build();
2114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2115 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2116 InputEventInjectionSync::WAIT_FOR_RESULT))
2117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2118 foregroundWindow->consumeMotionPointerUp(0);
2119 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2120
2121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002122 injectMotionEvent(mDispatcher,
2123 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2124 AINPUT_SOURCE_TOUCHSCREEN)
2125 .displayId(ADISPLAY_ID_DEFAULT)
2126 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2127 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002128 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002129 .x(100)
2130 .y(100))
2131 .build(),
2132 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002133 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2134 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2135 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002136}
2137
2138/**
2139 * Two windows: a window on the left and window on the right.
2140 * A third window, wallpaper, is behind both windows, and spans both top windows.
2141 * The first touch down goes to the left window. A second pointer touches down on the right window.
2142 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2143 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2144 * ACTION_POINTER_DOWN(1).
2145 */
2146TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2148 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002149 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002150 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002151 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002152
2153 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002154 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002155 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002156 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002157
2158 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002159 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002160 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002161 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002162
2163 mDispatcher->setInputWindows(
2164 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2165
2166 // Touch down on left window
2167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2168 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2169 {100, 100}))
2170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2171
2172 // Both foreground window and its wallpaper should receive the touch down
2173 leftWindow->consumeMotionDown();
2174 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2175
2176 // Second finger down on the right window
2177 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002178 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002179 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002180 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2181 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002182 .build();
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2184 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2185 InputEventInjectionSync::WAIT_FOR_RESULT))
2186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2187
2188 leftWindow->consumeMotionMove();
2189 // Since the touch is split, right window gets ACTION_DOWN
2190 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002191 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002192 expectedWallpaperFlags);
2193
2194 // Now, leftWindow, which received the first finger, disappears.
2195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2196 leftWindow->consumeMotionCancel();
2197 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2198 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2199
2200 // The pointer that's still down on the right window moves, and goes to the right window only.
2201 // As far as the dispatcher's concerned though, both pointers are still present.
2202 const MotionEvent secondFingerMoveEvent =
2203 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2204 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002205 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2206 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002207 .build();
2208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2209 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2210 InputEventInjectionSync::WAIT_FOR_RESULT));
2211 rightWindow->consumeMotionMove();
2212
2213 leftWindow->assertNoEvents();
2214 rightWindow->assertNoEvents();
2215 wallpaperWindow->assertNoEvents();
2216}
2217
Arthur Hungc539dbb2022-12-08 07:45:36 +00002218/**
2219 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2220 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2221 * The right window should receive ACTION_DOWN.
2222 */
2223TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002225 sp<FakeWindowHandle> leftWindow =
2226 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2227 leftWindow->setFrame(Rect(0, 0, 200, 200));
2228 leftWindow->setDupTouchToWallpaper(true);
2229 leftWindow->setSlippery(true);
2230
2231 sp<FakeWindowHandle> rightWindow =
2232 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2233 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002234
2235 sp<FakeWindowHandle> wallpaperWindow =
2236 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2237 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002238
Arthur Hungc539dbb2022-12-08 07:45:36 +00002239 mDispatcher->setInputWindows(
2240 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002241
Arthur Hungc539dbb2022-12-08 07:45:36 +00002242 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2244 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002245 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002247
2248 // Both foreground window and its wallpaper should receive the touch down
2249 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002250 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2251
Arthur Hungc539dbb2022-12-08 07:45:36 +00002252 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002254 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2255 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2257
Arthur Hungc539dbb2022-12-08 07:45:36 +00002258 leftWindow->consumeMotionCancel();
2259 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2260 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002261}
2262
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002263/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002264 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2265 * interactive, it might stop sending this flag.
2266 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2267 * to have a consistent input stream.
2268 *
2269 * Test procedure:
2270 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2271 * DOWN (new gesture).
2272 *
2273 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2274 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2275 *
2276 * We technically just need a single window here, but we are using two windows (spy on top and a
2277 * regular window below) to emulate the actual situation where it happens on the device.
2278 */
2279TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2281 sp<FakeWindowHandle> spyWindow =
2282 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2283 spyWindow->setFrame(Rect(0, 0, 200, 200));
2284 spyWindow->setTrustedOverlay(true);
2285 spyWindow->setSpy(true);
2286
2287 sp<FakeWindowHandle> window =
2288 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2289 window->setFrame(Rect(0, 0, 200, 200));
2290
2291 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2292 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002293
2294 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002295 mDispatcher->notifyMotion(
2296 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2297 .deviceId(touchDeviceId)
2298 .policyFlags(DEFAULT_POLICY_FLAGS)
2299 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2300 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002301
Prabir Pradhan678438e2023-04-13 19:32:51 +00002302 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2303 .deviceId(touchDeviceId)
2304 .policyFlags(DEFAULT_POLICY_FLAGS)
2305 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2306 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2307 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002308 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2309 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2310 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2311 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2312
2313 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002314 mDispatcher->notifyMotion(
2315 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2316 .deviceId(touchDeviceId)
2317 .policyFlags(0)
2318 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2319 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2320 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002321 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2322 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2323
2324 // We don't need to reset the device to reproduce the issue, but the reset event typically
2325 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002326 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002327
2328 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002329 mDispatcher->notifyMotion(
2330 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2331 .deviceId(touchDeviceId)
2332 .policyFlags(DEFAULT_POLICY_FLAGS)
2333 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2334 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002335 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2336 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2337
2338 // No more events
2339 spyWindow->assertNoEvents();
2340 window->assertNoEvents();
2341}
2342
2343/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002344 * Two windows: a window on the left and a window on the right.
2345 * Mouse is hovered from the right window into the left window.
2346 * Next, we tap on the left window, where the cursor was last seen.
2347 * The second tap is done onto the right window.
2348 * The mouse and tap are from two different devices.
2349 * We technically don't need to set the downtime / eventtime for these events, but setting these
2350 * explicitly helps during debugging.
2351 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2352 * In the buggy implementation, a tap on the right window would cause a crash.
2353 */
2354TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2355 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2356 sp<FakeWindowHandle> leftWindow =
2357 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2358 leftWindow->setFrame(Rect(0, 0, 200, 200));
2359
2360 sp<FakeWindowHandle> rightWindow =
2361 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2362 rightWindow->setFrame(Rect(200, 0, 400, 200));
2363
2364 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2365 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2366 // stale.
2367 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2368 const int32_t mouseDeviceId = 6;
2369 const int32_t touchDeviceId = 4;
2370 // Move the cursor from right
2371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2372 injectMotionEvent(mDispatcher,
2373 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2374 AINPUT_SOURCE_MOUSE)
2375 .deviceId(mouseDeviceId)
2376 .downTime(baseTime + 10)
2377 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002378 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002379 .x(300)
2380 .y(100))
2381 .build()));
2382 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2383
2384 // .. to the left window
2385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2386 injectMotionEvent(mDispatcher,
2387 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2388 AINPUT_SOURCE_MOUSE)
2389 .deviceId(mouseDeviceId)
2390 .downTime(baseTime + 10)
2391 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002392 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002393 .x(110)
2394 .y(100))
2395 .build()));
2396 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2397 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2398 // Now tap the left window
2399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2400 injectMotionEvent(mDispatcher,
2401 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2402 AINPUT_SOURCE_TOUCHSCREEN)
2403 .deviceId(touchDeviceId)
2404 .downTime(baseTime + 40)
2405 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002406 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002407 .x(100)
2408 .y(100))
2409 .build()));
2410 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2411 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2412
2413 // release tap
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2415 injectMotionEvent(mDispatcher,
2416 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 40)
2420 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002421 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002422 .x(100)
2423 .y(100))
2424 .build()));
2425 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2426
2427 // Tap the window on the right
2428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2429 injectMotionEvent(mDispatcher,
2430 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2431 AINPUT_SOURCE_TOUCHSCREEN)
2432 .deviceId(touchDeviceId)
2433 .downTime(baseTime + 60)
2434 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002435 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002436 .x(300)
2437 .y(100))
2438 .build()));
2439 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2440
2441 // release tap
2442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2443 injectMotionEvent(mDispatcher,
2444 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2445 AINPUT_SOURCE_TOUCHSCREEN)
2446 .deviceId(touchDeviceId)
2447 .downTime(baseTime + 60)
2448 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002449 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002450 .x(300)
2451 .y(100))
2452 .build()));
2453 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2454
2455 // No more events
2456 leftWindow->assertNoEvents();
2457 rightWindow->assertNoEvents();
2458}
2459
2460/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002461 * Two windows: a window on the left and a window on the right.
2462 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2463 * down. Then, on the left window, also place second touch pointer down.
2464 * This test tries to reproduce a crash.
2465 * In the buggy implementation, second pointer down on the left window would cause a crash.
2466 */
2467TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2468 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2469 sp<FakeWindowHandle> leftWindow =
2470 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2471 leftWindow->setFrame(Rect(0, 0, 200, 200));
2472
2473 sp<FakeWindowHandle> rightWindow =
2474 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2475 rightWindow->setFrame(Rect(200, 0, 400, 200));
2476
2477 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2478
2479 const int32_t touchDeviceId = 4;
2480 const int32_t mouseDeviceId = 6;
2481 NotifyMotionArgs args;
2482
2483 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2485 .deviceId(mouseDeviceId)
2486 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2487 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002488 leftWindow->consumeMotionEvent(
2489 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2490
2491 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2493 .deviceId(mouseDeviceId)
2494 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2495 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2496 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002497
2498 leftWindow->consumeMotionEvent(
2499 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2500 leftWindow->consumeMotionEvent(
2501 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2502
Prabir Pradhan678438e2023-04-13 19:32:51 +00002503 mDispatcher->notifyMotion(
2504 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2505 .deviceId(mouseDeviceId)
2506 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2507 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2508 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2509 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002510 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2511
2512 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2514 .deviceId(touchDeviceId)
2515 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2516 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002517 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2518
2519 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2520
2521 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002522 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2523 .deviceId(touchDeviceId)
2524 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2525 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2526 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002527 leftWindow->consumeMotionEvent(
2528 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2529 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2530 // current implementation.
2531 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2532 rightWindow->consumeMotionEvent(
2533 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2534
2535 leftWindow->assertNoEvents();
2536 rightWindow->assertNoEvents();
2537}
2538
2539/**
2540 * On a single window, use two different devices: mouse and touch.
2541 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2542 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2543 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2544 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2545 * represent a new gesture.
2546 */
2547TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2549 sp<FakeWindowHandle> window =
2550 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2551 window->setFrame(Rect(0, 0, 400, 400));
2552
2553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2554
2555 const int32_t touchDeviceId = 4;
2556 const int32_t mouseDeviceId = 6;
2557 NotifyMotionArgs args;
2558
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002559 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2561 .deviceId(touchDeviceId)
2562 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2563 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002564 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002565 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2566 .deviceId(touchDeviceId)
2567 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2568 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2569 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002570 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002571 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2572 .deviceId(touchDeviceId)
2573 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2574 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2575 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002576 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2577 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2578 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2579
2580 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2585 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002586
2587 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002588 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002589 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2590
Prabir Pradhan678438e2023-04-13 19:32:51 +00002591 mDispatcher->notifyMotion(
2592 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2593 .deviceId(mouseDeviceId)
2594 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2595 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2596 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2597 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002598 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2599
2600 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002601 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2602 .deviceId(touchDeviceId)
2603 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2604 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2605 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002606 // The pointer_down event should be ignored
2607 window->assertNoEvents();
2608}
2609
2610/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002611 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2612 * the injected event.
2613 */
2614TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2616 sp<FakeWindowHandle> window =
2617 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2618 window->setFrame(Rect(0, 0, 400, 400));
2619
2620 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2621
2622 const int32_t touchDeviceId = 4;
2623 NotifyMotionArgs args;
2624 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2625 // completion.
2626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2627 injectMotionEvent(mDispatcher,
2628 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2629 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002630 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002631 .x(50)
2632 .y(50))
2633 .build()));
2634 window->consumeMotionEvent(
2635 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2636
2637 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2638 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2642 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002643
2644 window->consumeMotionEvent(
2645 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2646 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2647}
2648
2649/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002650 * This test is similar to the test above, but the sequence of injected events is different.
2651 *
2652 * Two windows: a window on the left and a window on the right.
2653 * Mouse is hovered over the left window.
2654 * Next, we tap on the left window, where the cursor was last seen.
2655 *
2656 * After that, we inject one finger down onto the right window, and then a second finger down onto
2657 * the left window.
2658 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2659 * window (first), and then another on the left window (second).
2660 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2661 * In the buggy implementation, second finger down on the left window would cause a crash.
2662 */
2663TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2665 sp<FakeWindowHandle> leftWindow =
2666 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2667 leftWindow->setFrame(Rect(0, 0, 200, 200));
2668
2669 sp<FakeWindowHandle> rightWindow =
2670 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2671 rightWindow->setFrame(Rect(200, 0, 400, 200));
2672
2673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2674
2675 const int32_t mouseDeviceId = 6;
2676 const int32_t touchDeviceId = 4;
2677 // Hover over the left window. Keep the cursor there.
2678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2679 injectMotionEvent(mDispatcher,
2680 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2681 AINPUT_SOURCE_MOUSE)
2682 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002683 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002684 .x(50)
2685 .y(50))
2686 .build()));
2687 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2688
2689 // Tap on left window
2690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2691 injectMotionEvent(mDispatcher,
2692 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2693 AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002695 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002696 .x(100)
2697 .y(100))
2698 .build()));
2699
2700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2701 injectMotionEvent(mDispatcher,
2702 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2703 AINPUT_SOURCE_TOUCHSCREEN)
2704 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002705 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002706 .x(100)
2707 .y(100))
2708 .build()));
2709 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2710 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2711 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2712
2713 // First finger down on right window
2714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2715 injectMotionEvent(mDispatcher,
2716 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2717 AINPUT_SOURCE_TOUCHSCREEN)
2718 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002719 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002720 .x(300)
2721 .y(100))
2722 .build()));
2723 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2724
2725 // Second finger down on the left window
2726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2727 injectMotionEvent(mDispatcher,
2728 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2729 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002730 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002731 .x(300)
2732 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002733 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002734 .x(100)
2735 .y(100))
2736 .build()));
2737 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2738 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2739
2740 // No more events
2741 leftWindow->assertNoEvents();
2742 rightWindow->assertNoEvents();
2743}
2744
2745/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002746 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2747 * While the touch is down, new hover events from the stylus device should be ignored. After the
2748 * touch is gone, stylus hovering should start working again.
2749 */
2750TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2752 sp<FakeWindowHandle> window =
2753 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2754 window->setFrame(Rect(0, 0, 200, 200));
2755
2756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2757
2758 const int32_t stylusDeviceId = 5;
2759 const int32_t touchDeviceId = 4;
2760 // Start hovering with stylus
2761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2762 injectMotionEvent(mDispatcher,
2763 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2764 AINPUT_SOURCE_STYLUS)
2765 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002766 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002767 .x(50)
2768 .y(50))
2769 .build()));
2770 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2771
2772 // Finger down on the window
2773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2774 injectMotionEvent(mDispatcher,
2775 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2776 AINPUT_SOURCE_TOUCHSCREEN)
2777 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002778 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002779 .x(100)
2780 .y(100))
2781 .build()));
2782 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2783 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2784
2785 // Try to continue hovering with stylus. Since we are already down, injection should fail
2786 ASSERT_EQ(InputEventInjectionResult::FAILED,
2787 injectMotionEvent(mDispatcher,
2788 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2789 AINPUT_SOURCE_STYLUS)
2790 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002791 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002792 .x(50)
2793 .y(50))
2794 .build()));
2795 // No event should be sent. This event should be ignored because a pointer from another device
2796 // is already down.
2797
2798 // Lift up the finger
2799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2800 injectMotionEvent(mDispatcher,
2801 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2802 AINPUT_SOURCE_TOUCHSCREEN)
2803 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002804 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002805 .x(100)
2806 .y(100))
2807 .build()));
2808 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2809
2810 // Now that the touch is gone, stylus hovering should start working again
2811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2812 injectMotionEvent(mDispatcher,
2813 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2814 AINPUT_SOURCE_STYLUS)
2815 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002816 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002817 .x(50)
2818 .y(50))
2819 .build()));
2820 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2821 // No more events
2822 window->assertNoEvents();
2823}
2824
2825/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002826 * A spy window above a window with no input channel.
2827 * Start hovering with a stylus device, and then tap with it.
2828 * Ensure spy window receives the entire sequence.
2829 */
2830TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2832 sp<FakeWindowHandle> spyWindow =
2833 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2834 spyWindow->setFrame(Rect(0, 0, 200, 200));
2835 spyWindow->setTrustedOverlay(true);
2836 spyWindow->setSpy(true);
2837 sp<FakeWindowHandle> window =
2838 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2839 window->setNoInputChannel(true);
2840 window->setFrame(Rect(0, 0, 200, 200));
2841
2842 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2843
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2846 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2847 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002848 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2849 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2852 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002853 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2854
2855 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2857 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2858 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002859 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2860
2861 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2863 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2864 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002865 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2866
2867 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002868 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2869 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2870 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002871 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2872 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2874 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2875 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002876 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2877
2878 // No more events
2879 spyWindow->assertNoEvents();
2880 window->assertNoEvents();
2881}
2882
2883/**
2884 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2885 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2886 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2887 * While the mouse is down, new move events from the touch device should be ignored.
2888 */
2889TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2891 sp<FakeWindowHandle> spyWindow =
2892 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2893 spyWindow->setFrame(Rect(0, 0, 200, 200));
2894 spyWindow->setTrustedOverlay(true);
2895 spyWindow->setSpy(true);
2896 sp<FakeWindowHandle> window =
2897 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2898 window->setFrame(Rect(0, 0, 200, 200));
2899
2900 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2901
2902 const int32_t mouseDeviceId = 7;
2903 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002904
2905 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2907 .deviceId(mouseDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2909 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002910 spyWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2912 window->consumeMotionEvent(
2913 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2914
2915 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2917 .deviceId(touchDeviceId)
2918 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2919 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002920 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2921 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2922 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2923 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2924
Prabir Pradhan678438e2023-04-13 19:32:51 +00002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2926 .deviceId(touchDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2928 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002929 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2930 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2931
2932 // Pilfer the stream
2933 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2934 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2935
Prabir Pradhan678438e2023-04-13 19:32:51 +00002936 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2937 .deviceId(touchDeviceId)
2938 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2939 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002940 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2941
2942 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002943 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2944 .deviceId(mouseDeviceId)
2945 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2946 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2947 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002948
2949 spyWindow->consumeMotionEvent(
2950 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2951 spyWindow->consumeMotionEvent(
2952 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2953 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2954
Prabir Pradhan678438e2023-04-13 19:32:51 +00002955 mDispatcher->notifyMotion(
2956 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2957 .deviceId(mouseDeviceId)
2958 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2959 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2960 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2961 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002962 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2963 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2964
2965 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002966 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2967 .deviceId(mouseDeviceId)
2968 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2969 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2970 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002971 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2972 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2973
2974 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2976 .deviceId(touchDeviceId)
2977 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2978 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002979
2980 // No more events
2981 spyWindow->assertNoEvents();
2982 window->assertNoEvents();
2983}
2984
2985/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002986 * On the display, have a single window, and also an area where there's no window.
2987 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2988 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2989 */
2990TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2992 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002993 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002994
2995 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002996
2997 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002998 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002999
3000 mDispatcher->waitForIdle();
3001 window->assertNoEvents();
3002
3003 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003004 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003005 mDispatcher->waitForIdle();
3006 window->consumeMotionDown();
3007}
3008
3009/**
3010 * Same test as above, but instead of touching the empty space, the first touch goes to
3011 * non-touchable window.
3012 */
3013TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3015 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003016 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003017 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3018 window1->setTouchable(false);
3019 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003020 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003021 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3022
3023 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3024
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003025 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003026 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003027
3028 mDispatcher->waitForIdle();
3029 window1->assertNoEvents();
3030 window2->assertNoEvents();
3031
3032 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003033 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003034 mDispatcher->waitForIdle();
3035 window2->consumeMotionDown();
3036}
3037
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003038/**
3039 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3040 * to the event time of the first ACTION_DOWN sent to the particular window.
3041 */
3042TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3044 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003045 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003046 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3047 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003048 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003049 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3050
3051 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3052
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003053 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003054 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003055
3056 mDispatcher->waitForIdle();
3057 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003058 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003059 window2->assertNoEvents();
3060 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3061 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3062 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3063
3064 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003065 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003066 mDispatcher->waitForIdle();
3067 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003068 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003069 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3070 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3071 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3072 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3073
3074 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003075 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003076 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003077 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003078
3079 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003080 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003081 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003082 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003083
3084 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3085 window1->consumeMotionMove();
3086 window1->assertNoEvents();
3087
3088 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003089 mDispatcher->notifyMotion(
3090 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003091 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003092 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003093
Prabir Pradhan678438e2023-04-13 19:32:51 +00003094 mDispatcher->notifyMotion(
3095 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003096 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003097 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003098}
3099
Garfield Tandf26e862020-07-01 20:18:19 -07003100TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003102 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003103 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003104 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003105 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003106 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003107 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003108
3109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3110
3111 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3112
3113 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003115 injectMotionEvent(mDispatcher,
3116 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3117 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003118 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003119 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003120 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003121
3122 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003124 injectMotionEvent(mDispatcher,
3125 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3126 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003127 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003128 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003129 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3130 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003131
3132 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003134 injectMotionEvent(mDispatcher,
3135 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3136 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003137 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003138 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3140 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003141
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003142 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003143 injectMotionEvent(mDispatcher,
3144 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3145 AINPUT_SOURCE_MOUSE)
3146 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3147 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003148 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003149 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003150 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003151
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003153 injectMotionEvent(mDispatcher,
3154 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3155 AINPUT_SOURCE_MOUSE)
3156 .buttonState(0)
3157 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003158 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003159 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003160 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003161
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003163 injectMotionEvent(mDispatcher,
3164 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3165 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003167 .build()));
3168 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3169
3170 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003172 injectMotionEvent(mDispatcher,
3173 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3174 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003175 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003176 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003177 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003178
3179 // No more events
3180 windowLeft->assertNoEvents();
3181 windowRight->assertNoEvents();
3182}
3183
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003184/**
3185 * Put two fingers down (and don't release them) and click the mouse button.
3186 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3187 * currently active gesture should be canceled, and the new one should proceed.
3188 */
3189TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3191 sp<FakeWindowHandle> window =
3192 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3193 window->setFrame(Rect(0, 0, 600, 800));
3194
3195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3196
3197 const int32_t touchDeviceId = 4;
3198 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199
3200 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003201 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3202 .deviceId(touchDeviceId)
3203 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3204 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205
Prabir Pradhan678438e2023-04-13 19:32:51 +00003206 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3207 .deviceId(touchDeviceId)
3208 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3209 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3210 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003211 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3212 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3213
3214 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3216 .deviceId(mouseDeviceId)
3217 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3218 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3219 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003220 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3221 WithPointerCount(2u)));
3222 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3223
Prabir Pradhan678438e2023-04-13 19:32:51 +00003224 mDispatcher->notifyMotion(
3225 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3226 .deviceId(mouseDeviceId)
3227 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3228 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3229 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3230 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003231 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3232
3233 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3234 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3236 .deviceId(touchDeviceId)
3237 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3238 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3239 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003240 window->assertNoEvents();
3241}
3242
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003243TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3245
3246 sp<FakeWindowHandle> spyWindow =
3247 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3248 spyWindow->setFrame(Rect(0, 0, 600, 800));
3249 spyWindow->setTrustedOverlay(true);
3250 spyWindow->setSpy(true);
3251 sp<FakeWindowHandle> window =
3252 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3253 window->setFrame(Rect(0, 0, 600, 800));
3254
3255 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3256 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3257
3258 // Send mouse cursor to the window
3259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3260 injectMotionEvent(mDispatcher,
3261 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3262 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003263 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003264 .x(100)
3265 .y(100))
3266 .build()));
3267
3268 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3269 WithSource(AINPUT_SOURCE_MOUSE)));
3270 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3271 WithSource(AINPUT_SOURCE_MOUSE)));
3272
3273 window->assertNoEvents();
3274 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003275}
3276
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003277TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3279
3280 sp<FakeWindowHandle> spyWindow =
3281 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3282 spyWindow->setFrame(Rect(0, 0, 600, 800));
3283 spyWindow->setTrustedOverlay(true);
3284 spyWindow->setSpy(true);
3285 sp<FakeWindowHandle> window =
3286 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3287 window->setFrame(Rect(0, 0, 600, 800));
3288
3289 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3291
3292 // Send mouse cursor to the window
3293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3294 injectMotionEvent(mDispatcher,
3295 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3296 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003297 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003298 .x(100)
3299 .y(100))
3300 .build()));
3301
3302 // Move mouse cursor
3303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3304 injectMotionEvent(mDispatcher,
3305 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3306 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003307 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003308 .x(110)
3309 .y(110))
3310 .build()));
3311
3312 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3313 WithSource(AINPUT_SOURCE_MOUSE)));
3314 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3315 WithSource(AINPUT_SOURCE_MOUSE)));
3316 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3317 WithSource(AINPUT_SOURCE_MOUSE)));
3318 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3319 WithSource(AINPUT_SOURCE_MOUSE)));
3320 // Touch down on the window
3321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3322 injectMotionEvent(mDispatcher,
3323 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3324 AINPUT_SOURCE_TOUCHSCREEN)
3325 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003326 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003327 .x(200)
3328 .y(200))
3329 .build()));
3330 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3331 WithSource(AINPUT_SOURCE_MOUSE)));
3332 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3333 WithSource(AINPUT_SOURCE_MOUSE)));
3334 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3335 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3336 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3337 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3338
3339 // pilfer the motion, retaining the gesture on the spy window.
3340 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3341 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3342 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3343
3344 // Touch UP on the window
3345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3346 injectMotionEvent(mDispatcher,
3347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3348 AINPUT_SOURCE_TOUCHSCREEN)
3349 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003350 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003351 .x(200)
3352 .y(200))
3353 .build()));
3354 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3355 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3356
3357 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3358 // to send a new gesture. It should again go to both windows (spy and the window below), just
3359 // like the first gesture did, before pilfering. The window configuration has not changed.
3360
3361 // One more tap - DOWN
3362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3363 injectMotionEvent(mDispatcher,
3364 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3365 AINPUT_SOURCE_TOUCHSCREEN)
3366 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003367 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003368 .x(250)
3369 .y(250))
3370 .build()));
3371 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3372 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3373 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3374 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3375
3376 // Touch UP on the window
3377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3378 injectMotionEvent(mDispatcher,
3379 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3380 AINPUT_SOURCE_TOUCHSCREEN)
3381 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003382 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003383 .x(250)
3384 .y(250))
3385 .build()));
3386 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3387 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3388 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3389 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3390
3391 window->assertNoEvents();
3392 spyWindow->assertNoEvents();
3393}
3394
Garfield Tandf26e862020-07-01 20:18:19 -07003395// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3396// directly in this test.
3397TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003399 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003400 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003401 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003402
3403 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3404
3405 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3406
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003408 injectMotionEvent(mDispatcher,
3409 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3410 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003411 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003412 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003413 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003414 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003416 injectMotionEvent(mDispatcher,
3417 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3418 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003420 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003421 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3422 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003423
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003425 injectMotionEvent(mDispatcher,
3426 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3427 AINPUT_SOURCE_MOUSE)
3428 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3429 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003430 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003431 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003432 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003433
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003435 injectMotionEvent(mDispatcher,
3436 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3437 AINPUT_SOURCE_MOUSE)
3438 .buttonState(0)
3439 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003440 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003441 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003442 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003443
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003445 injectMotionEvent(mDispatcher,
3446 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3447 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003449 .build()));
3450 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3451
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003453 injectMotionEvent(mDispatcher,
3454 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3455 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003456 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003457 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003458 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003459}
3460
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003461/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003462 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3463 * is generated.
3464 */
3465TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3467 sp<FakeWindowHandle> window =
3468 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3469 window->setFrame(Rect(0, 0, 1200, 800));
3470
3471 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3472
3473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3474
3475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3476 injectMotionEvent(mDispatcher,
3477 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3478 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003479 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003480 .x(300)
3481 .y(400))
3482 .build()));
3483 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3484
3485 // Remove the window, but keep the channel.
3486 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3487 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3488}
3489
3490/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003491 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3492 */
3493TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3495 sp<FakeWindowHandle> window =
3496 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3497 window->setFrame(Rect(0, 0, 100, 100));
3498
3499 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3500
3501 const int32_t mouseDeviceId = 7;
3502 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003503
3504 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3506 .deviceId(mouseDeviceId)
3507 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3508 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003509 window->consumeMotionEvent(
3510 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3511
3512 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3514 .deviceId(touchDeviceId)
3515 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3516 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003517
3518 window->consumeMotionEvent(
3519 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3520 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3521}
3522
3523/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003524 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003525 * The tap causes a HOVER_EXIT event to be generated because the current event
3526 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003527 */
3528TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3530 sp<FakeWindowHandle> window =
3531 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3532 window->setFrame(Rect(0, 0, 100, 100));
3533
3534 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3535
3536 // Inject a hover_move from mouse.
3537 NotifyMotionArgs motionArgs =
3538 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3539 ADISPLAY_ID_DEFAULT, {{50, 50}});
3540 motionArgs.xCursorPosition = 50;
3541 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003542 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003543 ASSERT_NO_FATAL_FAILURE(
3544 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3545 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003546
3547 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3549 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3550 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003551 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003552 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3553 WithSource(AINPUT_SOURCE_MOUSE))));
3554
3555 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003556 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3557 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3558
Prabir Pradhan678438e2023-04-13 19:32:51 +00003559 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3560 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003561 ASSERT_NO_FATAL_FAILURE(
3562 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3563 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3564}
3565
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003566TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3568 sp<FakeWindowHandle> windowDefaultDisplay =
3569 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3570 ADISPLAY_ID_DEFAULT);
3571 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3572 sp<FakeWindowHandle> windowSecondDisplay =
3573 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3574 SECOND_DISPLAY_ID);
3575 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3576
3577 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3578 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3579
3580 // Set cursor position in window in default display and check that hover enter and move
3581 // events are generated.
3582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3583 injectMotionEvent(mDispatcher,
3584 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3585 AINPUT_SOURCE_MOUSE)
3586 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003587 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003588 .x(300)
3589 .y(600))
3590 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003591 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003592
3593 // Remove all windows in secondary display and check that no event happens on window in
3594 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003595 mDispatcher->setInputWindows(
3596 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003597 windowDefaultDisplay->assertNoEvents();
3598
3599 // Move cursor position in window in default display and check that only hover move
3600 // event is generated and not hover enter event.
3601 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3602 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3604 injectMotionEvent(mDispatcher,
3605 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3606 AINPUT_SOURCE_MOUSE)
3607 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003608 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003609 .x(400)
3610 .y(700))
3611 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003612 windowDefaultDisplay->consumeMotionEvent(
3613 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3614 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003615 windowDefaultDisplay->assertNoEvents();
3616}
3617
Garfield Tan00f511d2019-06-12 16:55:40 -07003618TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003620
3621 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003622 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003623 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003624 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003625 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003626 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003627
3628 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3629
Arthur Hung72d8dc32020-03-28 00:48:39 +00003630 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003631
3632 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3633 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003635 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003636 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003637 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003638 windowRight->assertNoEvents();
3639}
3640
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003641TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003643 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3644 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003645 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003646
Arthur Hung72d8dc32020-03-28 00:48:39 +00003647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003648 setFocusedWindow(window);
3649
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003650 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003651
Prabir Pradhan678438e2023-04-13 19:32:51 +00003652 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003653
3654 // Window should receive key down event.
3655 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3656
3657 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3658 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003659 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003660 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003661 AKEY_EVENT_FLAG_CANCELED);
3662}
3663
3664TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003666 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3667 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003668
Arthur Hung72d8dc32020-03-28 00:48:39 +00003669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003670
Prabir Pradhan678438e2023-04-13 19:32:51 +00003671 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3672 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003673
3674 // Window should receive motion down event.
3675 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3676
3677 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3678 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003679 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003680 window->consumeMotionEvent(
3681 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003682}
3683
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003684TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3687 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003688 window->setFocusable(true);
3689
3690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3691 setFocusedWindow(window);
3692
3693 window->consumeFocusEvent(true);
3694
Prabir Pradhan678438e2023-04-13 19:32:51 +00003695 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003696 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3697 const nsecs_t injectTime = keyArgs.eventTime;
3698 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003699 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003700 // The dispatching time should be always greater than or equal to intercept key timeout.
3701 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3702 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3703 std::chrono::nanoseconds(interceptKeyTimeout).count());
3704}
3705
3706TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003708 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3709 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003710 window->setFocusable(true);
3711
3712 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3713 setFocusedWindow(window);
3714
3715 window->consumeFocusEvent(true);
3716
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003717 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003718 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3719 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003720
3721 // Window should receive key event immediately when same key up.
3722 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3723 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3724}
3725
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003726/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003727 * Two windows. First is a regular window. Second does not overlap with the first, and has
3728 * WATCH_OUTSIDE_TOUCH.
3729 * Both windows are owned by the same UID.
3730 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3731 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3732 */
3733TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3734 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3735 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3736 "First Window", ADISPLAY_ID_DEFAULT);
3737 window->setFrame(Rect{0, 0, 100, 100});
3738
3739 sp<FakeWindowHandle> outsideWindow =
3740 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3741 ADISPLAY_ID_DEFAULT);
3742 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3743 outsideWindow->setWatchOutsideTouch(true);
3744 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3745 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3746
3747 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003748 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3749 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3750 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003751 window->consumeMotionDown();
3752 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3753 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3754 outsideWindow->consumeMotionEvent(
3755 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3756}
3757
3758/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003759 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3760 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3761 * ACTION_OUTSIDE event is sent per gesture.
3762 */
3763TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3764 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003766 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3767 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003768 window->setWatchOutsideTouch(true);
3769 window->setFrame(Rect{0, 0, 100, 100});
3770 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003771 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3772 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003773 secondWindow->setFrame(Rect{100, 100, 200, 200});
3774 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003775 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3776 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003777 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3779
3780 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003781 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3782 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3783 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003784 window->assertNoEvents();
3785 secondWindow->assertNoEvents();
3786
3787 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3788 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3790 ADISPLAY_ID_DEFAULT,
3791 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003792 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3793 window->consumeMotionEvent(
3794 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003795 secondWindow->consumeMotionDown();
3796 thirdWindow->assertNoEvents();
3797
3798 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3799 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003800 mDispatcher->notifyMotion(
3801 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3802 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003803 window->assertNoEvents();
3804 secondWindow->consumeMotionMove();
3805 thirdWindow->consumeMotionDown();
3806}
3807
Prabir Pradhan814fe082022-07-22 20:22:18 +00003808TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003810 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3811 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003812 window->setFocusable(true);
3813
3814 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3815 setFocusedWindow(window);
3816
3817 window->consumeFocusEvent(true);
3818
Prabir Pradhan678438e2023-04-13 19:32:51 +00003819 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3820 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3821 mDispatcher->notifyKey(keyDown);
3822 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003823
3824 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3825 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3826
3827 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
3828 mDispatcher->onWindowInfosChanged({}, {});
3829
3830 window->consumeFocusEvent(false);
3831
Prabir Pradhan678438e2023-04-13 19:32:51 +00003832 mDispatcher->notifyKey(keyDown);
3833 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003834 window->assertNoEvents();
3835}
3836
Arthur Hung96483742022-11-15 03:30:48 +00003837TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3839 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3840 "Fake Window", ADISPLAY_ID_DEFAULT);
3841 // Ensure window is non-split and have some transform.
3842 window->setPreventSplitting(true);
3843 window->setWindowOffset(20, 40);
3844 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {});
3845
3846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3847 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3848 {50, 50}))
3849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3850 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3851
3852 const MotionEvent secondFingerDownEvent =
3853 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3854 .displayId(ADISPLAY_ID_DEFAULT)
3855 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003856 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3857 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003858 .build();
3859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3860 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3861 InputEventInjectionSync::WAIT_FOR_RESULT))
3862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3863
3864 const MotionEvent* event = window->consumeMotion();
3865 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3866 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3867 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3868 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3869 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3870}
3871
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003872/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003873 * Ensure the correct coordinate spaces are used by InputDispatcher.
3874 *
3875 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3876 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3877 * space.
3878 */
3879class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3880public:
3881 void SetUp() override {
3882 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003883 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003884 }
3885
3886 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3887 gui::DisplayInfo info;
3888 info.displayId = displayId;
3889 info.transform = transform;
3890 mDisplayInfos.push_back(std::move(info));
3891 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3892 }
3893
3894 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3895 mWindowInfos.push_back(*windowHandle->getInfo());
3896 mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos);
3897 }
3898
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003899 void removeAllWindowsAndDisplays() {
3900 mDisplayInfos.clear();
3901 mWindowInfos.clear();
3902 }
3903
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003904 // Set up a test scenario where the display has a scaled projection and there are two windows
3905 // on the display.
3906 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3907 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3908 // respectively.
3909 ui::Transform displayTransform;
3910 displayTransform.set(2, 0, 0, 4);
3911 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3912
3913 std::shared_ptr<FakeApplicationHandle> application =
3914 std::make_shared<FakeApplicationHandle>();
3915
3916 // Add two windows to the display. Their frames are represented in the display space.
3917 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003918 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3919 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003920 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3921 addWindow(firstWindow);
3922
3923 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003924 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3925 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003926 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3927 addWindow(secondWindow);
3928 return {std::move(firstWindow), std::move(secondWindow)};
3929 }
3930
3931private:
3932 std::vector<gui::DisplayInfo> mDisplayInfos;
3933 std::vector<gui::WindowInfo> mWindowInfos;
3934};
3935
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003936TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003937 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3938 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003939 // selected so that if the hit test was performed with the point and the bounds being in
3940 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003941 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3942 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3943 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003944
3945 firstWindow->consumeMotionDown();
3946 secondWindow->assertNoEvents();
3947}
3948
3949// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3950// the event should be treated as being in the logical display space.
3951TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3952 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3953 // Send down to the first window. The point is represented in the logical display space. The
3954 // point is selected so that if the hit test was done in logical display space, then it would
3955 // end up in the incorrect window.
3956 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3957 PointF{75 * 2, 55 * 4});
3958
3959 firstWindow->consumeMotionDown();
3960 secondWindow->assertNoEvents();
3961}
3962
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003963// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
3964// event should be treated as being in the logical display space.
3965TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
3966 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3967
3968 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
3969 ui::Transform injectedEventTransform;
3970 injectedEventTransform.set(matrix);
3971 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
3972 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
3973
3974 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3975 .displayId(ADISPLAY_ID_DEFAULT)
3976 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003977 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00003978 .x(untransformedPoint.x)
3979 .y(untransformedPoint.y))
3980 .build();
3981 event.transform(matrix);
3982
3983 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
3984 InputEventInjectionSync::WAIT_FOR_RESULT);
3985
3986 firstWindow->consumeMotionDown();
3987 secondWindow->assertNoEvents();
3988}
3989
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003990TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
3991 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3992
3993 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003994 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3995 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3996 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003997
3998 firstWindow->assertNoEvents();
3999 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004000 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004001 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4002
4003 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4004 EXPECT_EQ(300, event->getRawX(0));
4005 EXPECT_EQ(880, event->getRawY(0));
4006
4007 // Ensure that the x and y values are in the window's coordinate space.
4008 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4009 // the logical display space. This will be the origin of the window space.
4010 EXPECT_EQ(100, event->getX(0));
4011 EXPECT_EQ(80, event->getY(0));
4012}
4013
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004014/** Ensure consistent behavior of InputDispatcher in all orientations. */
4015class InputDispatcherDisplayOrientationFixture
4016 : public InputDispatcherDisplayProjectionTest,
4017 public ::testing::WithParamInterface<ui::Rotation> {};
4018
4019// This test verifies the touchable region of a window for all rotations of the display by tapping
4020// in different locations on the display, specifically points close to the four corners of a
4021// window.
4022TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4023 constexpr static int32_t displayWidth = 400;
4024 constexpr static int32_t displayHeight = 800;
4025
4026 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4027
4028 const auto rotation = GetParam();
4029
4030 // Set up the display with the specified rotation.
4031 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4032 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4033 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4034 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4035 logicalDisplayWidth, logicalDisplayHeight);
4036 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4037
4038 // Create a window with its bounds determined in the logical display.
4039 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4040 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4041 sp<FakeWindowHandle> window =
4042 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4043 window->setFrame(frameInDisplay, displayTransform);
4044 addWindow(window);
4045
4046 // The following points in logical display space should be inside the window.
4047 static const std::array<vec2, 4> insidePoints{
4048 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4049 for (const auto pointInsideWindow : insidePoints) {
4050 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4051 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004052 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4053 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4054 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004055 window->consumeMotionDown();
4056
Prabir Pradhan678438e2023-04-13 19:32:51 +00004057 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4058 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4059 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004060 window->consumeMotionUp();
4061 }
4062
4063 // The following points in logical display space should be outside the window.
4064 static const std::array<vec2, 5> outsidePoints{
4065 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4066 for (const auto pointOutsideWindow : outsidePoints) {
4067 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4068 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004069 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4070 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4071 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004072
Prabir Pradhan678438e2023-04-13 19:32:51 +00004073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4074 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4075 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004076 }
4077 window->assertNoEvents();
4078}
4079
4080// Run the precision tests for all rotations.
4081INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4082 InputDispatcherDisplayOrientationFixture,
4083 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4084 ui::ROTATION_270),
4085 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4086 return ftl::enum_string(testParamInfo.param);
4087 });
4088
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004089using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4090 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004091
4092class TransferTouchFixture : public InputDispatcherTest,
4093 public ::testing::WithParamInterface<TransferFunction> {};
4094
4095TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004097
4098 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004099 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004100 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4101 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004102 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004103 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004104 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4105 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004106 sp<FakeWindowHandle> wallpaper =
4107 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4108 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004109 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004110 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004111
4112 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4114 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004115
Svet Ganov5d3bc372020-01-26 23:11:07 -08004116 // Only the first window should get the down event
4117 firstWindow->consumeMotionDown();
4118 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004119 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004120
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004121 // Transfer touch to the second window
4122 TransferFunction f = GetParam();
4123 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4124 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004125 // The first window gets cancel and the second gets down
4126 firstWindow->consumeMotionCancel();
4127 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004128 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004129
4130 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004131 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4132 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004133 // The first window gets no events and the second gets up
4134 firstWindow->assertNoEvents();
4135 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004136 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004137}
4138
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004139/**
4140 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4141 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4142 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4143 * natural to the user.
4144 * In this test, we are sending a pointer to both spy window and first window. We then try to
4145 * transfer touch to the second window. The dispatcher should identify the first window as the
4146 * one that should lose the gesture, and therefore the action should be to move the gesture from
4147 * the first window to the second.
4148 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4149 * the other API, as well.
4150 */
4151TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4152 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4153
4154 // Create a couple of windows + a spy window
4155 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004156 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004157 spyWindow->setTrustedOverlay(true);
4158 spyWindow->setSpy(true);
4159 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004160 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004161 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004162 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004163
4164 // Add the windows to the dispatcher
4165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4166
4167 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004168 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4169 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004170 // Only the first window and spy should get the down event
4171 spyWindow->consumeMotionDown();
4172 firstWindow->consumeMotionDown();
4173
4174 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4175 // if f === 'transferTouch'.
4176 TransferFunction f = GetParam();
4177 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4178 ASSERT_TRUE(success);
4179 // The first window gets cancel and the second gets down
4180 firstWindow->consumeMotionCancel();
4181 secondWindow->consumeMotionDown();
4182
4183 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004184 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4185 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004186 // The first window gets no events and the second+spy get up
4187 firstWindow->assertNoEvents();
4188 spyWindow->consumeMotionUp();
4189 secondWindow->consumeMotionUp();
4190}
4191
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004192TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004194
4195 PointF touchPoint = {10, 10};
4196
4197 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004198 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004199 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4200 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004201 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004202 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004203 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4204 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004205 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004206
4207 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004209
4210 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004211 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4212 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4213 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004214 // Only the first window should get the down event
4215 firstWindow->consumeMotionDown();
4216 secondWindow->assertNoEvents();
4217
4218 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004219 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4220 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004221 // Only the first window should get the pointer down event
4222 firstWindow->consumeMotionPointerDown(1);
4223 secondWindow->assertNoEvents();
4224
4225 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004226 TransferFunction f = GetParam();
4227 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4228 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004229 // The first window gets cancel and the second gets down and pointer down
4230 firstWindow->consumeMotionCancel();
4231 secondWindow->consumeMotionDown();
4232 secondWindow->consumeMotionPointerDown(1);
4233
4234 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004235 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4236 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004237 // The first window gets nothing and the second gets pointer up
4238 firstWindow->assertNoEvents();
4239 secondWindow->consumeMotionPointerUp(1);
4240
4241 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004242 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4243 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244 // The first window gets nothing and the second gets up
4245 firstWindow->assertNoEvents();
4246 secondWindow->consumeMotionUp();
4247}
4248
Arthur Hungc539dbb2022-12-08 07:45:36 +00004249TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4250 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4251
4252 // Create a couple of windows
4253 sp<FakeWindowHandle> firstWindow =
4254 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4255 ADISPLAY_ID_DEFAULT);
4256 firstWindow->setDupTouchToWallpaper(true);
4257 sp<FakeWindowHandle> secondWindow =
4258 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4259 ADISPLAY_ID_DEFAULT);
4260 secondWindow->setDupTouchToWallpaper(true);
4261
4262 sp<FakeWindowHandle> wallpaper1 =
4263 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4264 wallpaper1->setIsWallpaper(true);
4265
4266 sp<FakeWindowHandle> wallpaper2 =
4267 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4268 wallpaper2->setIsWallpaper(true);
4269 // Add the windows to the dispatcher
4270 mDispatcher->setInputWindows(
4271 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4272
4273 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004274 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4275 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004276
4277 // Only the first window should get the down event
4278 firstWindow->consumeMotionDown();
4279 secondWindow->assertNoEvents();
4280 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4281 wallpaper2->assertNoEvents();
4282
4283 // Transfer touch focus to the second window
4284 TransferFunction f = GetParam();
4285 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4286 ASSERT_TRUE(success);
4287
4288 // The first window gets cancel and the second gets down
4289 firstWindow->consumeMotionCancel();
4290 secondWindow->consumeMotionDown();
4291 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4292 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4293
4294 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4296 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004297 // The first window gets no events and the second gets up
4298 firstWindow->assertNoEvents();
4299 secondWindow->consumeMotionUp();
4300 wallpaper1->assertNoEvents();
4301 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4302}
4303
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004304// For the cases of single pointer touch and two pointers non-split touch, the api's
4305// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4306// for the case where there are multiple pointers split across several windows.
4307INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4308 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004309 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4310 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004311 return dispatcher->transferTouch(destChannelToken,
4312 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004313 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004314 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4315 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004316 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004317 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004318 }));
4319
Svet Ganov5d3bc372020-01-26 23:11:07 -08004320TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004322
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004323 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004324 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4325 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004326 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004327
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004328 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004329 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4330 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004331 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004332
4333 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004335
4336 PointF pointInFirst = {300, 200};
4337 PointF pointInSecond = {300, 600};
4338
4339 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004340 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4341 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4342 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004343 // Only the first window should get the down event
4344 firstWindow->consumeMotionDown();
4345 secondWindow->assertNoEvents();
4346
4347 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004348 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4349 ADISPLAY_ID_DEFAULT,
4350 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004351 // The first window gets a move and the second a down
4352 firstWindow->consumeMotionMove();
4353 secondWindow->consumeMotionDown();
4354
4355 // Transfer touch focus to the second window
4356 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4357 // The first window gets cancel and the new gets pointer down (it already saw down)
4358 firstWindow->consumeMotionCancel();
4359 secondWindow->consumeMotionPointerDown(1);
4360
4361 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004362 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4363 ADISPLAY_ID_DEFAULT,
4364 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004365 // The first window gets nothing and the second gets pointer up
4366 firstWindow->assertNoEvents();
4367 secondWindow->consumeMotionPointerUp(1);
4368
4369 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4371 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004372 // The first window gets nothing and the second gets up
4373 firstWindow->assertNoEvents();
4374 secondWindow->consumeMotionUp();
4375}
4376
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004377// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4378// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4379// touch is not supported, so the touch should continue on those windows and the transferred-to
4380// window should get nothing.
4381TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4383
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004384 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004385 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4386 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004387 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004388
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004389 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004390 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4391 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004392 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004393
4394 // Add the windows to the dispatcher
4395 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4396
4397 PointF pointInFirst = {300, 200};
4398 PointF pointInSecond = {300, 600};
4399
4400 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004401 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4402 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4403 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004404 // Only the first window should get the down event
4405 firstWindow->consumeMotionDown();
4406 secondWindow->assertNoEvents();
4407
4408 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004409 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4410 ADISPLAY_ID_DEFAULT,
4411 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004412 // The first window gets a move and the second a down
4413 firstWindow->consumeMotionMove();
4414 secondWindow->consumeMotionDown();
4415
4416 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004417 const bool transferred =
4418 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004419 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4420 ASSERT_FALSE(transferred);
4421 firstWindow->assertNoEvents();
4422 secondWindow->assertNoEvents();
4423
4424 // The rest of the dispatch should proceed as normal
4425 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004426 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4427 ADISPLAY_ID_DEFAULT,
4428 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004429 // The first window gets MOVE and the second gets pointer up
4430 firstWindow->consumeMotionMove();
4431 secondWindow->consumeMotionUp();
4432
4433 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004434 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4435 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004436 // The first window gets nothing and the second gets up
4437 firstWindow->consumeMotionUp();
4438 secondWindow->assertNoEvents();
4439}
4440
Arthur Hungabbb9d82021-09-01 14:52:30 +00004441// This case will create two windows and one mirrored window on the default display and mirror
4442// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4443// the windows info of second display before default display.
4444TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4446 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004447 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004448 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004449 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004450 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004451 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004452
4453 sp<FakeWindowHandle> mirrorWindowInPrimary =
4454 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4455 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004456
4457 sp<FakeWindowHandle> firstWindowInSecondary =
4458 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4459 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004460
4461 sp<FakeWindowHandle> secondWindowInSecondary =
4462 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4463 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004464
4465 // Update window info, let it find window handle of second display first.
4466 mDispatcher->setInputWindows(
4467 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4468 {ADISPLAY_ID_DEFAULT,
4469 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4470
4471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4472 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4473 {50, 50}))
4474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4475
4476 // Window should receive motion event.
4477 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4478
4479 // Transfer touch focus
4480 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4481 secondWindowInPrimary->getToken()));
4482 // The first window gets cancel.
4483 firstWindowInPrimary->consumeMotionCancel();
4484 secondWindowInPrimary->consumeMotionDown();
4485
4486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4487 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4488 ADISPLAY_ID_DEFAULT, {150, 50}))
4489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4490 firstWindowInPrimary->assertNoEvents();
4491 secondWindowInPrimary->consumeMotionMove();
4492
4493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4494 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4495 {150, 50}))
4496 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4497 firstWindowInPrimary->assertNoEvents();
4498 secondWindowInPrimary->consumeMotionUp();
4499}
4500
4501// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4502// 'transferTouch' api.
4503TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4505 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004506 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004507 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004508 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004509 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004510 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004511
4512 sp<FakeWindowHandle> mirrorWindowInPrimary =
4513 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4514 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004515
4516 sp<FakeWindowHandle> firstWindowInSecondary =
4517 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4518 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004519
4520 sp<FakeWindowHandle> secondWindowInSecondary =
4521 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4522 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004523
4524 // Update window info, let it find window handle of second display first.
4525 mDispatcher->setInputWindows(
4526 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4527 {ADISPLAY_ID_DEFAULT,
4528 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4529
4530 // Touch on second display.
4531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4532 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4534
4535 // Window should receive motion event.
4536 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4537
4538 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004539 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004540
4541 // The first window gets cancel.
4542 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4543 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4544
4545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4546 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4547 SECOND_DISPLAY_ID, {150, 50}))
4548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4549 firstWindowInPrimary->assertNoEvents();
4550 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4551
4552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4553 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4554 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4555 firstWindowInPrimary->assertNoEvents();
4556 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4557}
4558
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004559TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
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
Vishnu Nair47074b82020-08-14 11:54:47 -07004564 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004566 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004567
4568 window->consumeFocusEvent(true);
4569
Prabir Pradhan678438e2023-04-13 19:32:51 +00004570 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004571
4572 // Window should receive key down event.
4573 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004574
4575 // Should have poked user activity
4576 mFakePolicy->assertUserActivityPoked();
4577}
4578
4579TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4581 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4582 "Fake Window", ADISPLAY_ID_DEFAULT);
4583
4584 window->setDisableUserActivity(true);
4585 window->setFocusable(true);
4586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4587 setFocusedWindow(window);
4588
4589 window->consumeFocusEvent(true);
4590
4591 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4592
4593 // Window should receive key down event.
4594 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4595
4596 // Should have poked user activity
4597 mFakePolicy->assertUserActivityNotPoked();
4598}
4599
4600TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4602 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4603 "Fake Window", ADISPLAY_ID_DEFAULT);
4604
4605 window->setFocusable(true);
4606 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4607 setFocusedWindow(window);
4608
4609 window->consumeFocusEvent(true);
4610
4611 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4612 mDispatcher->waitForIdle();
4613
4614 // System key is not passed down
4615 window->assertNoEvents();
4616
4617 // Should have poked user activity
4618 mFakePolicy->assertUserActivityPoked();
4619}
4620
4621TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4623 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4624 "Fake Window", ADISPLAY_ID_DEFAULT);
4625
4626 window->setFocusable(true);
4627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4628 setFocusedWindow(window);
4629
4630 window->consumeFocusEvent(true);
4631
4632 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4633 mDispatcher->waitForIdle();
4634
4635 // System key is not passed down
4636 window->assertNoEvents();
4637
4638 // Should have poked user activity
4639 mFakePolicy->assertUserActivityPoked();
4640}
4641
4642TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4644 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4645 "Fake Window", ADISPLAY_ID_DEFAULT);
4646
4647 window->setDisableUserActivity(true);
4648 window->setFocusable(true);
4649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4650 setFocusedWindow(window);
4651
4652 window->consumeFocusEvent(true);
4653
4654 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4655 mDispatcher->waitForIdle();
4656
4657 // System key is not passed down
4658 window->assertNoEvents();
4659
4660 // Should have poked user activity
4661 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004662}
4663
4664TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004666 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4667 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004668
Arthur Hung72d8dc32020-03-28 00:48:39 +00004669 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004670
Prabir Pradhan678438e2023-04-13 19:32:51 +00004671 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004672 mDispatcher->waitForIdle();
4673
4674 window->assertNoEvents();
4675}
4676
4677// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4678TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004680 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4681 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004682
Arthur Hung72d8dc32020-03-28 00:48:39 +00004683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004684
4685 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004686 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004687 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004688 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4689 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004690
4691 // Window should receive only the motion event
4692 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4693 window->assertNoEvents(); // Key event or focus event will not be received
4694}
4695
arthurhungea3f4fc2020-12-21 23:18:53 +08004696TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4698
arthurhungea3f4fc2020-12-21 23:18:53 +08004699 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004700 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4701 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004702 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004703
arthurhungea3f4fc2020-12-21 23:18:53 +08004704 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004705 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4706 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004707 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004708
4709 // Add the windows to the dispatcher
4710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4711
4712 PointF pointInFirst = {300, 200};
4713 PointF pointInSecond = {300, 600};
4714
4715 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004716 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4717 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4718 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004719 // Only the first window should get the down event
4720 firstWindow->consumeMotionDown();
4721 secondWindow->assertNoEvents();
4722
4723 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004724 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4725 ADISPLAY_ID_DEFAULT,
4726 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004727 // The first window gets a move and the second a down
4728 firstWindow->consumeMotionMove();
4729 secondWindow->consumeMotionDown();
4730
4731 // Send pointer cancel to the second window
4732 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004733 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004734 {pointInFirst, pointInSecond});
4735 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004736 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004737 // The first window gets move and the second gets cancel.
4738 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4739 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4740
4741 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004742 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4743 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004744 // The first window gets up and the second gets nothing.
4745 firstWindow->consumeMotionUp();
4746 secondWindow->assertNoEvents();
4747}
4748
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004749TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4750 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4751
4752 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004753 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4755 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4756 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4757 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4758
Harry Cutts33476232023-01-30 19:57:29 +00004759 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004760 window->assertNoEvents();
4761 mDispatcher->waitForIdle();
4762}
4763
chaviwd1c23182019-12-20 18:44:56 -08004764class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004765public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004766 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004767 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004768 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004769 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004770 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004771 }
4772
chaviwd1c23182019-12-20 18:44:56 -08004773 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4774
4775 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004776 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4777 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004778 }
4779
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004780 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4781
4782 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4783
chaviwd1c23182019-12-20 18:44:56 -08004784 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004785 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004786 expectedDisplayId, expectedFlags);
4787 }
4788
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004789 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004790 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004791 expectedDisplayId, expectedFlags);
4792 }
4793
chaviwd1c23182019-12-20 18:44:56 -08004794 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004795 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004796 expectedDisplayId, expectedFlags);
4797 }
4798
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004799 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004800 mInputReceiver->consumeMotionEvent(
4801 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4802 WithDisplayId(expectedDisplayId),
4803 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004804 }
4805
Arthur Hungfbfa5722021-11-16 02:45:54 +00004806 void consumeMotionPointerDown(int32_t pointerIdx) {
4807 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4808 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004809 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004810 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004811 }
4812
Evan Rosky84f07f02021-04-16 10:42:42 -07004813 MotionEvent* consumeMotion() {
4814 InputEvent* event = mInputReceiver->consume();
4815 if (!event) {
4816 ADD_FAILURE() << "No event was produced";
4817 return nullptr;
4818 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004819 if (event->getType() != InputEventType::MOTION) {
4820 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004821 return nullptr;
4822 }
4823 return static_cast<MotionEvent*>(event);
4824 }
4825
chaviwd1c23182019-12-20 18:44:56 -08004826 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4827
4828private:
4829 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004830};
4831
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004832using InputDispatcherMonitorTest = InputDispatcherTest;
4833
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004834/**
4835 * Two entities that receive touch: A window, and a global monitor.
4836 * The touch goes to the window, and then the window disappears.
4837 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4838 * for the monitor, as well.
4839 * 1. foregroundWindow
4840 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4841 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004842TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4844 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004845 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004846
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004847 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004848
4849 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4851 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4852 {100, 200}))
4853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4854
4855 // Both the foreground window and the global monitor should receive the touch down
4856 window->consumeMotionDown();
4857 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4858
4859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4860 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4861 ADISPLAY_ID_DEFAULT, {110, 200}))
4862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4863
4864 window->consumeMotionMove();
4865 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4866
4867 // Now the foreground window goes away
4868 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4869 window->consumeMotionCancel();
4870 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4871
4872 // If more events come in, there will be no more foreground window to send them to. This will
4873 // cause a cancel for the monitor, as well.
4874 ASSERT_EQ(InputEventInjectionResult::FAILED,
4875 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4876 ADISPLAY_ID_DEFAULT, {120, 200}))
4877 << "Injection should fail because the window was removed";
4878 window->assertNoEvents();
4879 // Global monitor now gets the cancel
4880 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4881}
4882
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004883TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004885 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4886 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004888
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004889 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004890
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004892 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004894 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004895 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004896}
4897
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004898TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4899 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004900
Chris Yea209fde2020-07-22 13:54:51 -07004901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004902 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4903 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004904 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004905
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004907 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004909 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004910 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004911
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004912 // Pilfer pointers from the monitor.
4913 // This should not do anything and the window should continue to receive events.
4914 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004915
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004917 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4918 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004920
4921 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4922 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004923}
4924
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004925TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004927 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4928 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4930 window->setWindowOffset(20, 40);
4931 window->setWindowTransform(0, 1, -1, 0);
4932
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004933 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004934
4935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4936 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
4937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4938 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4939 MotionEvent* event = monitor.consumeMotion();
4940 // Even though window has transform, gesture monitor must not.
4941 ASSERT_EQ(ui::Transform(), event->getTransform());
4942}
4943
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004944TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00004945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004946 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00004947
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004948 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00004949 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004950 << "Injection should fail if there is a monitor, but no touchable window";
4951 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00004952}
4953
chaviw81e2bb92019-12-18 15:03:51 -08004954TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004956 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4957 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08004958
Arthur Hung72d8dc32020-03-28 00:48:39 +00004959 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08004960
4961 NotifyMotionArgs motionArgs =
4962 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4963 ADISPLAY_ID_DEFAULT);
4964
Prabir Pradhan678438e2023-04-13 19:32:51 +00004965 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08004966 // Window should receive motion down event.
4967 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4968
4969 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08004970 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08004971 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
4972 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4973 motionArgs.pointerCoords[0].getX() - 10);
4974
Prabir Pradhan678438e2023-04-13 19:32:51 +00004975 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004976 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004977 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08004978}
4979
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004980/**
4981 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
4982 * the device default right away. In the test scenario, we check both the default value,
4983 * and the action of enabling / disabling.
4984 */
4985TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07004986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004987 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4988 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08004989 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004990
4991 // Set focused application.
4992 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07004993 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004994
4995 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00004996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004997 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00004998 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004999
5000 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005001 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005002 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005003 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005004
5005 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005006 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005007 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005008 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005009 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005011 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005012 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005013
5014 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005015 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005017 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005018
5019 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005020 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005021 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005022 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005023 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005025 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005026 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005027
5028 window->assertNoEvents();
5029}
5030
Gang Wange9087892020-01-07 12:17:14 -05005031TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005033 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5034 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005035
5036 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005037 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005038
Arthur Hung72d8dc32020-03-28 00:48:39 +00005039 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005040 setFocusedWindow(window);
5041
Harry Cutts33476232023-01-30 19:57:29 +00005042 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005043
Prabir Pradhan678438e2023-04-13 19:32:51 +00005044 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5045 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005046
5047 InputEvent* event = window->consume();
5048 ASSERT_NE(event, nullptr);
5049
5050 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5051 ASSERT_NE(verified, nullptr);
5052 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5053
5054 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5055 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5056 ASSERT_EQ(keyArgs.source, verified->source);
5057 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5058
5059 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5060
5061 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005062 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005063 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005064 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5065 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5066 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5067 ASSERT_EQ(0, verifiedKey.repeatCount);
5068}
5069
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005070TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005072 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5073 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005074
5075 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5076
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005077 ui::Transform transform;
5078 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5079
5080 gui::DisplayInfo displayInfo;
5081 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5082 displayInfo.transform = transform;
5083
5084 mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005085
Prabir Pradhan678438e2023-04-13 19:32:51 +00005086 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005087 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5088 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005089 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005090
5091 InputEvent* event = window->consume();
5092 ASSERT_NE(event, nullptr);
5093
5094 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5095 ASSERT_NE(verified, nullptr);
5096 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5097
5098 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5099 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5100 EXPECT_EQ(motionArgs.source, verified->source);
5101 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5102
5103 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5104
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005105 const vec2 rawXY =
5106 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5107 motionArgs.pointerCoords[0].getXYValue());
5108 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5109 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005110 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005111 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005112 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005113 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5114 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5115}
5116
chaviw09c8d2d2020-08-24 15:48:26 -07005117/**
5118 * Ensure that separate calls to sign the same data are generating the same key.
5119 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5120 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5121 * tests.
5122 */
5123TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5124 KeyEvent event = getTestKeyEvent();
5125 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5126
5127 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5128 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5129 ASSERT_EQ(hmac1, hmac2);
5130}
5131
5132/**
5133 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5134 */
5135TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5136 KeyEvent event = getTestKeyEvent();
5137 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5138 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5139
5140 verifiedEvent.deviceId += 1;
5141 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5142
5143 verifiedEvent.source += 1;
5144 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5145
5146 verifiedEvent.eventTimeNanos += 1;
5147 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5148
5149 verifiedEvent.displayId += 1;
5150 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5151
5152 verifiedEvent.action += 1;
5153 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5154
5155 verifiedEvent.downTimeNanos += 1;
5156 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5157
5158 verifiedEvent.flags += 1;
5159 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5160
5161 verifiedEvent.keyCode += 1;
5162 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5163
5164 verifiedEvent.scanCode += 1;
5165 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5166
5167 verifiedEvent.metaState += 1;
5168 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5169
5170 verifiedEvent.repeatCount += 1;
5171 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5172}
5173
Vishnu Nair958da932020-08-21 17:12:37 -07005174TEST_F(InputDispatcherTest, SetFocusedWindow) {
5175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5176 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005177 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005178 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005179 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5181
5182 // Top window is also focusable but is not granted focus.
5183 windowTop->setFocusable(true);
5184 windowSecond->setFocusable(true);
5185 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5186 setFocusedWindow(windowSecond);
5187
5188 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5190 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005191
5192 // Focused window should receive event.
5193 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5194 windowTop->assertNoEvents();
5195}
5196
5197TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5199 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005200 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005201 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5202
5203 window->setFocusable(true);
5204 // Release channel for window is no longer valid.
5205 window->releaseChannel();
5206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5207 setFocusedWindow(window);
5208
5209 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005210 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5211 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005212
5213 // window channel is invalid, so it should not receive any input event.
5214 window->assertNoEvents();
5215}
5216
5217TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5218 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5219 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005220 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005221 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005222 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5223
Vishnu Nair958da932020-08-21 17:12:37 -07005224 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5225 setFocusedWindow(window);
5226
5227 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005228 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5229 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005230
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005231 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005232 window->assertNoEvents();
5233}
5234
5235TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5236 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5237 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005238 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005239 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005240 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005241 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5242
5243 windowTop->setFocusable(true);
5244 windowSecond->setFocusable(true);
5245 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5246 setFocusedWindow(windowTop);
5247 windowTop->consumeFocusEvent(true);
5248
Chavi Weingarten847e8512023-03-29 00:26:09 +00005249 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005251 windowSecond->consumeFocusEvent(true);
5252 windowTop->consumeFocusEvent(false);
5253
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5255 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005256
5257 // Focused window should receive event.
5258 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5259}
5260
Chavi Weingarten847e8512023-03-29 00:26:09 +00005261TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005262 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5263 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005264 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005265 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005266 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005267 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5268
5269 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005270 windowSecond->setFocusable(false);
5271 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005272 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005273 setFocusedWindow(windowTop);
5274 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005275
Chavi Weingarten847e8512023-03-29 00:26:09 +00005276 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5277 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005278
5279 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005280 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005281 windowSecond->assertNoEvents();
5282}
5283
5284TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5286 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005287 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005288 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005289 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5290 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005291 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5292
5293 window->setFocusable(true);
5294 previousFocusedWindow->setFocusable(true);
5295 window->setVisible(false);
5296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5297 setFocusedWindow(previousFocusedWindow);
5298 previousFocusedWindow->consumeFocusEvent(true);
5299
5300 // Requesting focus on invisible window takes focus from currently focused window.
5301 setFocusedWindow(window);
5302 previousFocusedWindow->consumeFocusEvent(false);
5303
5304 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005306 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5307 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005308
5309 // Window does not get focus event or key down.
5310 window->assertNoEvents();
5311
5312 // Window becomes visible.
5313 window->setVisible(true);
5314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5315
5316 // Window receives focus event.
5317 window->consumeFocusEvent(true);
5318 // Focused window receives key down.
5319 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5320}
5321
Vishnu Nair599f1412021-06-21 10:39:58 -07005322TEST_F(InputDispatcherTest, DisplayRemoved) {
5323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5324 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005325 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005326 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5327
5328 // window is granted focus.
5329 window->setFocusable(true);
5330 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5331 setFocusedWindow(window);
5332 window->consumeFocusEvent(true);
5333
5334 // When a display is removed window loses focus.
5335 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5336 window->consumeFocusEvent(false);
5337}
5338
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005339/**
5340 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5341 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5342 * of the 'slipperyEnterWindow'.
5343 *
5344 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5345 * a way so that the touched location is no longer covered by the top window.
5346 *
5347 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5348 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5349 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5350 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5351 * with ACTION_DOWN).
5352 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5353 * window moved itself away from the touched location and had Flag::SLIPPERY.
5354 *
5355 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5356 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5357 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5358 *
5359 * In this test, we ensure that the event received by the bottom window has
5360 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5361 */
5362TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005363 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5364 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005365
5366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5367 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5368
5369 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005370 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005371 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005372 // Make sure this one overlaps the bottom window
5373 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5374 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5375 // one. Windows with the same owner are not considered to be occluding each other.
5376 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5377
5378 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005379 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005380 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5381
5382 mDispatcher->setInputWindows(
5383 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5384
5385 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005386 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5387 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5388 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005389 slipperyExitWindow->consumeMotionDown();
5390 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5391 mDispatcher->setInputWindows(
5392 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5393
Prabir Pradhan678438e2023-04-13 19:32:51 +00005394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5395 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5396 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005397
5398 slipperyExitWindow->consumeMotionCancel();
5399
5400 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5401 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5402}
5403
Garfield Tan1c7bc862020-01-28 13:24:04 -08005404class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5405protected:
5406 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5407 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5408
Chris Yea209fde2020-07-22 13:54:51 -07005409 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005410 sp<FakeWindowHandle> mWindow;
5411
5412 virtual void SetUp() override {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005413 mFakePolicy = sp<FakeInputDispatcherPolicy>::make();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005414 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005415 mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005416 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005417 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5418 ASSERT_EQ(OK, mDispatcher->start());
5419
5420 setUpWindow();
5421 }
5422
5423 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005424 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005425 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005426
Vishnu Nair47074b82020-08-14 11:54:47 -07005427 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005428 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005429 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005430 mWindow->consumeFocusEvent(true);
5431 }
5432
Chris Ye2ad95392020-09-01 13:44:44 -07005433 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005434 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005435 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005436 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005437 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005438
5439 // Window should receive key down event.
5440 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5441 }
5442
5443 void expectKeyRepeatOnce(int32_t repeatCount) {
5444 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5445 InputEvent* repeatEvent = mWindow->consume();
5446 ASSERT_NE(nullptr, repeatEvent);
5447
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005448 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005449
5450 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5451 uint32_t eventAction = repeatKeyEvent->getAction();
5452 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5453 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5454 }
5455
Chris Ye2ad95392020-09-01 13:44:44 -07005456 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005457 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005458 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005459 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005460 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005461
5462 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005463 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005464 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005465 }
5466};
5467
5468TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005469 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005470 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5471 expectKeyRepeatOnce(repeatCount);
5472 }
5473}
5474
5475TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005476 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005477 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5478 expectKeyRepeatOnce(repeatCount);
5479 }
Harry Cutts33476232023-01-30 19:57:29 +00005480 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005481 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005482 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5483 expectKeyRepeatOnce(repeatCount);
5484 }
5485}
5486
5487TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005488 sendAndConsumeKeyDown(/*deviceId=*/1);
5489 expectKeyRepeatOnce(/*repeatCount=*/1);
5490 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005491 mWindow->assertNoEvents();
5492}
5493
5494TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005495 sendAndConsumeKeyDown(/*deviceId=*/1);
5496 expectKeyRepeatOnce(/*repeatCount=*/1);
5497 sendAndConsumeKeyDown(/*deviceId=*/2);
5498 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005499 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005500 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005501 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005502 expectKeyRepeatOnce(/*repeatCount=*/2);
5503 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005504 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005505 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005506 mWindow->assertNoEvents();
5507}
5508
5509TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005510 sendAndConsumeKeyDown(/*deviceId=*/1);
5511 expectKeyRepeatOnce(/*repeatCount=*/1);
5512 sendAndConsumeKeyDown(/*deviceId=*/2);
5513 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005514 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005515 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005516 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005517 mWindow->assertNoEvents();
5518}
5519
liushenxiang42232912021-05-21 20:24:09 +08005520TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5521 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005522 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005523 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005524 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5525 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5526 mWindow->assertNoEvents();
5527}
5528
Garfield Tan1c7bc862020-01-28 13:24:04 -08005529TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005530 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005531 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005532 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5533 InputEvent* repeatEvent = mWindow->consume();
5534 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5535 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5536 IdGenerator::getSource(repeatEvent->getId()));
5537 }
5538}
5539
5540TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005541 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005542 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005543
5544 std::unordered_set<int32_t> idSet;
5545 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5546 InputEvent* repeatEvent = mWindow->consume();
5547 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5548 int32_t id = repeatEvent->getId();
5549 EXPECT_EQ(idSet.end(), idSet.find(id));
5550 idSet.insert(id);
5551 }
5552}
5553
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005554/* Test InputDispatcher for MultiDisplay */
5555class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5556public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005557 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005558 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005559
Chris Yea209fde2020-07-22 13:54:51 -07005560 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005561 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005562 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005563
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005564 // Set focus window for primary display, but focused display would be second one.
5565 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005566 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005568 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005569 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005570
Chris Yea209fde2020-07-22 13:54:51 -07005571 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005572 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005573 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005574 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005575 // Set focus display to second one.
5576 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5577 // Set focus window for second display.
5578 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005579 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005580 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005581 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005582 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005583 }
5584
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005585 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005586 InputDispatcherTest::TearDown();
5587
Chris Yea209fde2020-07-22 13:54:51 -07005588 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005589 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005590 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005591 windowInSecondary.clear();
5592 }
5593
5594protected:
Chris Yea209fde2020-07-22 13:54:51 -07005595 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005596 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005597 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005598 sp<FakeWindowHandle> windowInSecondary;
5599};
5600
5601TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5602 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5604 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005606 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005607 windowInSecondary->assertNoEvents();
5608
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005609 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5611 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005613 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005614 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005615}
5616
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005617TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005618 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5620 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005621 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005622 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005623 windowInSecondary->assertNoEvents();
5624
5625 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005627 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005628 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005629 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005630
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005631 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005632 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005633
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005634 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005635 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005636 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005637
5638 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005639 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005640 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005641 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005642 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005643 windowInSecondary->assertNoEvents();
5644}
5645
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005646// Test per-display input monitors for motion event.
5647TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005648 FakeMonitorReceiver monitorInPrimary =
5649 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5650 FakeMonitorReceiver monitorInSecondary =
5651 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005652
5653 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5655 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005657 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005658 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005659 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005660 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005661
5662 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5664 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005666 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005667 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005668 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005669 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005670
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005671 // Lift up the touch from the second display
5672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5673 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5675 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5676 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5677
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005678 // Test inject a non-pointer motion event.
5679 // If specific a display, it will dispatch to the focused window of particular display,
5680 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5682 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005684 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005685 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005686 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005687 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005688}
5689
5690// Test per-display input monitors for key event.
5691TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005692 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005693 FakeMonitorReceiver monitorInPrimary =
5694 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5695 FakeMonitorReceiver monitorInSecondary =
5696 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005697
5698 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005699 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5700 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005701 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005702 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005703 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005704 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005705}
5706
Vishnu Nair958da932020-08-21 17:12:37 -07005707TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5708 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005709 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005710 secondWindowInPrimary->setFocusable(true);
5711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5712 setFocusedWindow(secondWindowInPrimary);
5713 windowInPrimary->consumeFocusEvent(false);
5714 secondWindowInPrimary->consumeFocusEvent(true);
5715
5716 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5718 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005719 windowInPrimary->assertNoEvents();
5720 windowInSecondary->assertNoEvents();
5721 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5722}
5723
Arthur Hungdfd528e2021-12-08 13:23:04 +00005724TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5725 FakeMonitorReceiver monitorInPrimary =
5726 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5727 FakeMonitorReceiver monitorInSecondary =
5728 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5729
5730 // Test touch down on primary display.
5731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5732 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5734 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5735 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5736
5737 // Test touch down on second display.
5738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5739 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5741 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5742 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5743
5744 // Trigger cancel touch.
5745 mDispatcher->cancelCurrentTouch();
5746 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5747 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5748 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5749 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5750
5751 // Test inject a move motion event, no window/monitor should receive the event.
5752 ASSERT_EQ(InputEventInjectionResult::FAILED,
5753 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5754 ADISPLAY_ID_DEFAULT, {110, 200}))
5755 << "Inject motion event should return InputEventInjectionResult::FAILED";
5756 windowInPrimary->assertNoEvents();
5757 monitorInPrimary.assertNoEvents();
5758
5759 ASSERT_EQ(InputEventInjectionResult::FAILED,
5760 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5761 SECOND_DISPLAY_ID, {110, 200}))
5762 << "Inject motion event should return InputEventInjectionResult::FAILED";
5763 windowInSecondary->assertNoEvents();
5764 monitorInSecondary.assertNoEvents();
5765}
5766
Jackal Guof9696682018-10-05 12:23:23 +08005767class InputFilterTest : public InputDispatcherTest {
5768protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005769 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5770 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005771 NotifyMotionArgs motionArgs;
5772
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005773 motionArgs =
5774 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005775 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005776 motionArgs =
5777 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005778 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005779 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005780 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005781 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5782 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005783 } else {
5784 mFakePolicy->assertFilterInputEventWasNotCalled();
5785 }
5786 }
5787
5788 void testNotifyKey(bool expectToBeFiltered) {
5789 NotifyKeyArgs keyArgs;
5790
5791 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005792 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005793 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005794 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005795 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005796
5797 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08005798 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005799 } else {
5800 mFakePolicy->assertFilterInputEventWasNotCalled();
5801 }
5802 }
5803};
5804
5805// Test InputFilter for MotionEvent
5806TEST_F(InputFilterTest, MotionEvent_InputFilter) {
5807 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
5808 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5809 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5810
5811 // Enable InputFilter
5812 mDispatcher->setInputFilterEnabled(true);
5813 // Test touch on both primary and second display, and check if both events are filtered.
5814 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
5815 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
5816
5817 // Disable InputFilter
5818 mDispatcher->setInputFilterEnabled(false);
5819 // Test touch on both primary and second display, and check if both events aren't filtered.
5820 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
5821 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
5822}
5823
5824// Test InputFilter for KeyEvent
5825TEST_F(InputFilterTest, KeyEvent_InputFilter) {
5826 // Since the InputFilter is disabled by default, check if key event aren't filtered.
5827 testNotifyKey(/*expectToBeFiltered*/ false);
5828
5829 // Enable InputFilter
5830 mDispatcher->setInputFilterEnabled(true);
5831 // Send a key event, and check if it is filtered.
5832 testNotifyKey(/*expectToBeFiltered*/ true);
5833
5834 // Disable InputFilter
5835 mDispatcher->setInputFilterEnabled(false);
5836 // Send a key event, and check if it isn't filtered.
5837 testNotifyKey(/*expectToBeFiltered*/ false);
5838}
5839
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005840// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
5841// logical display coordinate space.
5842TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
5843 ui::Transform firstDisplayTransform;
5844 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5845 ui::Transform secondDisplayTransform;
5846 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
5847
5848 std::vector<gui::DisplayInfo> displayInfos(2);
5849 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
5850 displayInfos[0].transform = firstDisplayTransform;
5851 displayInfos[1].displayId = SECOND_DISPLAY_ID;
5852 displayInfos[1].transform = secondDisplayTransform;
5853
5854 mDispatcher->onWindowInfosChanged({}, displayInfos);
5855
5856 // Enable InputFilter
5857 mDispatcher->setInputFilterEnabled(true);
5858
5859 // Ensure the correct transforms are used for the displays.
5860 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
5861 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
5862}
5863
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005864class InputFilterInjectionPolicyTest : public InputDispatcherTest {
5865protected:
5866 virtual void SetUp() override {
5867 InputDispatcherTest::SetUp();
5868
5869 /**
5870 * We don't need to enable input filter to test the injected event policy, but we enabled it
5871 * here to make the tests more realistic, since this policy only matters when inputfilter is
5872 * on.
5873 */
5874 mDispatcher->setInputFilterEnabled(true);
5875
5876 std::shared_ptr<InputApplicationHandle> application =
5877 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005878 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
5879 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005880
5881 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5882 mWindow->setFocusable(true);
5883 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
5884 setFocusedWindow(mWindow);
5885 mWindow->consumeFocusEvent(true);
5886 }
5887
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005888 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5889 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005890 KeyEvent event;
5891
5892 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5893 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
5894 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00005895 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005896 const int32_t additionalPolicyFlags =
5897 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
5898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005899 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005900 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5901 policyFlags | additionalPolicyFlags));
5902
5903 InputEvent* received = mWindow->consume();
5904 ASSERT_NE(nullptr, received);
5905 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005906 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005907 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
5908 ASSERT_EQ(flags, keyEvent.getFlags());
5909 }
5910
5911 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
5912 int32_t flags) {
5913 MotionEvent event;
5914 PointerProperties pointerProperties[1];
5915 PointerCoords pointerCoords[1];
5916 pointerProperties[0].clear();
5917 pointerProperties[0].id = 0;
5918 pointerCoords[0].clear();
5919 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
5920 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
5921
5922 ui::Transform identityTransform;
5923 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5924 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
5925 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
5926 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
5927 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07005928 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07005929 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005930 /*pointerCount*/ 1, pointerProperties, pointerCoords);
5931
5932 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
5933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005934 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005935 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
5936 policyFlags | additionalPolicyFlags));
5937
5938 InputEvent* received = mWindow->consume();
5939 ASSERT_NE(nullptr, received);
5940 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005941 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005942 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
5943 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005944 }
5945
5946private:
5947 sp<FakeWindowHandle> mWindow;
5948};
5949
5950TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005951 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
5952 // filter. Without it, the event will no different from a regularly injected event, and the
5953 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00005954 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
5955 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005956}
5957
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005958TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005959 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005960 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005961 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5962}
5963
5964TEST_F(InputFilterInjectionPolicyTest,
5965 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
5966 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00005967 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00005968 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005969}
5970
5971TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00005972 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
5973 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00005974}
5975
chaviwfd6d3512019-03-25 13:23:49 -07005976class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005977 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07005978 InputDispatcherTest::SetUp();
5979
Chris Yea209fde2020-07-22 13:54:51 -07005980 std::shared_ptr<FakeApplicationHandle> application =
5981 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005982 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005983 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07005984 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07005985
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005986 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005987 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005988 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07005989
5990 // Set focused application.
5991 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005992 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07005993
5994 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005996 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005997 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07005998 }
5999
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006000 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006001 InputDispatcherTest::TearDown();
6002
6003 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006004 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006005 }
6006
6007protected:
6008 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006009 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006010 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006011};
6012
6013// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6014// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6015// the onPointerDownOutsideFocus callback.
6016TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006018 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6019 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006021 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006022
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006023 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006024 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6025}
6026
6027// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6028// DOWN on the window that doesn't have focus. Ensure no window received the
6029// onPointerDownOutsideFocus callback.
6030TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006032 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006034 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006035
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006036 ASSERT_TRUE(mDispatcher->waitForIdle());
6037 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006038}
6039
6040// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6041// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6042TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6044 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006045 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006046 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006047
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006048 ASSERT_TRUE(mDispatcher->waitForIdle());
6049 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006050}
6051
6052// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6053// DOWN on the window that already has focus. Ensure no window received the
6054// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006055TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006057 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006058 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006060 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006061
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006062 ASSERT_TRUE(mDispatcher->waitForIdle());
6063 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006064}
6065
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006066// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6067// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6068TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6069 const MotionEvent event =
6070 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6071 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006072 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006073 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6074 .build();
6075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6077 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6078
6079 ASSERT_TRUE(mDispatcher->waitForIdle());
6080 mFakePolicy->assertOnPointerDownWasNotCalled();
6081 // Ensure that the unfocused window did not receive any FOCUS events.
6082 mUnfocusedWindow->assertNoEvents();
6083}
6084
chaviwaf87b3e2019-10-01 16:59:28 -07006085// These tests ensures we can send touch events to a single client when there are multiple input
6086// windows that point to the same client token.
6087class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6088 virtual void SetUp() override {
6089 InputDispatcherTest::SetUp();
6090
Chris Yea209fde2020-07-22 13:54:51 -07006091 std::shared_ptr<FakeApplicationHandle> application =
6092 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006093 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6094 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006095 mWindow1->setFrame(Rect(0, 0, 100, 100));
6096
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006097 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6098 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006099 mWindow2->setFrame(Rect(100, 100, 200, 200));
6100
Arthur Hung72d8dc32020-03-28 00:48:39 +00006101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006102 }
6103
6104protected:
6105 sp<FakeWindowHandle> mWindow1;
6106 sp<FakeWindowHandle> mWindow2;
6107
6108 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006109 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006110 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6111 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006112 }
6113
6114 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6115 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006116 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006117 InputEvent* event = window->consume();
6118
6119 ASSERT_NE(nullptr, event) << name.c_str()
6120 << ": consumer should have returned non-NULL event.";
6121
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006122 ASSERT_EQ(InputEventType::MOTION, event->getType())
6123 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006124
6125 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006126 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006127 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006128
6129 for (size_t i = 0; i < points.size(); i++) {
6130 float expectedX = points[i].x;
6131 float expectedY = points[i].y;
6132
6133 EXPECT_EQ(expectedX, motionEvent.getX(i))
6134 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6135 << ", got " << motionEvent.getX(i);
6136 EXPECT_EQ(expectedY, motionEvent.getY(i))
6137 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6138 << ", got " << motionEvent.getY(i);
6139 }
6140 }
chaviw9eaa22c2020-07-01 16:21:27 -07006141
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006142 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006143 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006144 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6145 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006146
6147 // Always consume from window1 since it's the window that has the InputReceiver
6148 consumeMotionEvent(mWindow1, action, expectedPoints);
6149 }
chaviwaf87b3e2019-10-01 16:59:28 -07006150};
6151
6152TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6153 // Touch Window 1
6154 PointF touchedPoint = {10, 10};
6155 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006156 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006157
6158 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006159 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006160
6161 // Touch Window 2
6162 touchedPoint = {150, 150};
6163 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006164 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006165}
6166
chaviw9eaa22c2020-07-01 16:21:27 -07006167TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6168 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006169 mWindow2->setWindowScale(0.5f, 0.5f);
6170
6171 // Touch Window 1
6172 PointF touchedPoint = {10, 10};
6173 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006174 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006175 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006176 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006177
6178 // Touch Window 2
6179 touchedPoint = {150, 150};
6180 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006181 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6182 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006183
chaviw9eaa22c2020-07-01 16:21:27 -07006184 // Update the transform so rotation is set
6185 mWindow2->setWindowTransform(0, -1, 1, 0);
6186 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6187 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006188}
6189
chaviw9eaa22c2020-07-01 16:21:27 -07006190TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006191 mWindow2->setWindowScale(0.5f, 0.5f);
6192
6193 // Touch Window 1
6194 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6195 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006196 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006197
6198 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006199 touchedPoints.push_back(PointF{150, 150});
6200 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006201 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006202
chaviw9eaa22c2020-07-01 16:21:27 -07006203 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006204 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006205 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006206
chaviw9eaa22c2020-07-01 16:21:27 -07006207 // Update the transform so rotation is set for Window 2
6208 mWindow2->setWindowTransform(0, -1, 1, 0);
6209 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006210 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006211}
6212
chaviw9eaa22c2020-07-01 16:21:27 -07006213TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006214 mWindow2->setWindowScale(0.5f, 0.5f);
6215
6216 // Touch Window 1
6217 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6218 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006219 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006220
6221 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006222 touchedPoints.push_back(PointF{150, 150});
6223 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006224
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006225 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006226
6227 // Move both windows
6228 touchedPoints = {{20, 20}, {175, 175}};
6229 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6230 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6231
chaviw9eaa22c2020-07-01 16:21:27 -07006232 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006233
chaviw9eaa22c2020-07-01 16:21:27 -07006234 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006235 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006236 expectedPoints.pop_back();
6237
6238 // Touch Window 2
6239 mWindow2->setWindowTransform(0, -1, 1, 0);
6240 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006241 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006242
6243 // Move both windows
6244 touchedPoints = {{20, 20}, {175, 175}};
6245 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6246 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6247
6248 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006249}
6250
6251TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6252 mWindow1->setWindowScale(0.5f, 0.5f);
6253
6254 // Touch Window 1
6255 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6256 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006257 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006258
6259 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006260 touchedPoints.push_back(PointF{150, 150});
6261 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006262
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006263 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006264
6265 // Move both windows
6266 touchedPoints = {{20, 20}, {175, 175}};
6267 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6268 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6269
chaviw9eaa22c2020-07-01 16:21:27 -07006270 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006271}
6272
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006273/**
6274 * When one of the windows is slippery, the touch should not slip into the other window with the
6275 * same input channel.
6276 */
6277TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6278 mWindow1->setSlippery(true);
6279 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6280
6281 // Touch down in window 1
6282 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6283 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6284 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6285
6286 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6287 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6288 // getting generated.
6289 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6290 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6291
6292 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6293}
6294
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006295class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6296 virtual void SetUp() override {
6297 InputDispatcherTest::SetUp();
6298
Chris Yea209fde2020-07-22 13:54:51 -07006299 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006300 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006301 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6302 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006303 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006304 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006305 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006306
6307 // Set focused application.
6308 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6309
6310 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006311 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006312 mWindow->consumeFocusEvent(true);
6313 }
6314
6315 virtual void TearDown() override {
6316 InputDispatcherTest::TearDown();
6317 mWindow.clear();
6318 }
6319
6320protected:
Chris Yea209fde2020-07-22 13:54:51 -07006321 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006322 sp<FakeWindowHandle> mWindow;
6323 static constexpr PointF WINDOW_LOCATION = {20, 20};
6324
6325 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006327 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6328 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006330 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6331 WINDOW_LOCATION));
6332 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006333
6334 sp<FakeWindowHandle> addSpyWindow() {
6335 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006336 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006337 spy->setTrustedOverlay(true);
6338 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006339 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006340 spy->setDispatchingTimeout(30ms);
6341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6342 return spy;
6343 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006344};
6345
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006346// Send a tap and respond, which should not cause an ANR.
6347TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6348 tapOnWindow();
6349 mWindow->consumeMotionDown();
6350 mWindow->consumeMotionUp();
6351 ASSERT_TRUE(mDispatcher->waitForIdle());
6352 mFakePolicy->assertNotifyAnrWasNotCalled();
6353}
6354
6355// Send a regular key and respond, which should not cause an ANR.
6356TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006358 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6359 ASSERT_TRUE(mDispatcher->waitForIdle());
6360 mFakePolicy->assertNotifyAnrWasNotCalled();
6361}
6362
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006363TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6364 mWindow->setFocusable(false);
6365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6366 mWindow->consumeFocusEvent(false);
6367
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006368 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006369 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6370 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6371 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006373 // Key will not go to window because we have no focused window.
6374 // The 'no focused window' ANR timer should start instead.
6375
6376 // Now, the focused application goes away.
6377 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6378 // The key should get dropped and there should be no ANR.
6379
6380 ASSERT_TRUE(mDispatcher->waitForIdle());
6381 mFakePolicy->assertNotifyAnrWasNotCalled();
6382}
6383
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006384// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006385// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6386// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006387TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006389 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6390 WINDOW_LOCATION));
6391
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006392 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6393 ASSERT_TRUE(sequenceNum);
6394 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006395 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006396
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006397 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006398 mWindow->consumeMotionEvent(
6399 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006400 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006401 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006402}
6403
6404// Send a key to the app and have the app not respond right away.
6405TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6406 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006408 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6409 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006410 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006411 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006412 ASSERT_TRUE(mDispatcher->waitForIdle());
6413}
6414
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006415// We have a focused application, but no focused window
6416TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006417 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6419 mWindow->consumeFocusEvent(false);
6420
6421 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006423 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6424 WINDOW_LOCATION));
6425 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6426 mDispatcher->waitForIdle();
6427 mFakePolicy->assertNotifyAnrWasNotCalled();
6428
6429 // Once a focused event arrives, we get an ANR for this application
6430 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6431 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006432 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006433 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6434 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006435 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006436 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006437 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006438 ASSERT_TRUE(mDispatcher->waitForIdle());
6439}
6440
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006441/**
6442 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6443 * there will not be an ANR.
6444 */
6445TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6446 mWindow->setFocusable(false);
6447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6448 mWindow->consumeFocusEvent(false);
6449
6450 KeyEvent event;
6451 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6452 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6453
6454 // Define a valid key down event that is stale (too old).
6455 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6456 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006457 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006458
6459 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6460
6461 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006462 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006463 InputEventInjectionSync::WAIT_FOR_RESULT,
6464 INJECT_EVENT_TIMEOUT, policyFlags);
6465 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6466 << "Injection should fail because the event is stale";
6467
6468 ASSERT_TRUE(mDispatcher->waitForIdle());
6469 mFakePolicy->assertNotifyAnrWasNotCalled();
6470 mWindow->assertNoEvents();
6471}
6472
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006473// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006474// Make sure that we don't notify policy twice about the same ANR.
6475TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006476 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006477 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6478 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006479
6480 // Once a focused event arrives, we get an ANR for this application
6481 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6482 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006483 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006484 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6485 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006486 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006487 const std::chrono::duration appTimeout =
6488 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6489 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006490
Vishnu Naire4df8752022-09-08 09:17:55 -07006491 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006492 // ANR should not be raised again. It is up to policy to do that if it desires.
6493 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006494
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006495 // If we now get a focused window, the ANR should stop, but the policy handles that via
6496 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006497 ASSERT_TRUE(mDispatcher->waitForIdle());
6498}
6499
6500// We have a focused application, but no focused window
6501TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006502 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006503 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6504 mWindow->consumeFocusEvent(false);
6505
6506 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006507 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006508 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006509 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6510 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006511
Vishnu Naire4df8752022-09-08 09:17:55 -07006512 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6513 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006514
6515 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006516 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006517 ASSERT_TRUE(mDispatcher->waitForIdle());
6518 mWindow->assertNoEvents();
6519}
6520
6521/**
6522 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6523 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6524 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6525 * the ANR mechanism should still work.
6526 *
6527 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6528 * DOWN event, while not responding on the second one.
6529 */
6530TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6531 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6532 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6533 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6534 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6535 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006536 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006537
6538 // Now send ACTION_UP, with identical timestamp
6539 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6540 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6541 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6542 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006543 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006544
6545 // We have now sent down and up. Let's consume first event and then ANR on the second.
6546 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6547 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006548 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006549}
6550
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006551// A spy window can receive an ANR
6552TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6553 sp<FakeWindowHandle> spy = addSpyWindow();
6554
6555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6556 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6557 WINDOW_LOCATION));
6558 mWindow->consumeMotionDown();
6559
6560 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6561 ASSERT_TRUE(sequenceNum);
6562 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006563 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006564
6565 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006566 spy->consumeMotionEvent(
6567 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006568 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006569 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006570}
6571
6572// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006573// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006574TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6575 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006576
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6578 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006579 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006581
6582 // Stuck on the ACTION_UP
6583 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006584 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006585
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006586 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006587 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006588 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6589 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006590
6591 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6592 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006593 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006594 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006595 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006596}
6597
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006598// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006599// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006600TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6601 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006602
6603 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006604 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6605 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006606
6607 mWindow->consumeMotionDown();
6608 // Stuck on the ACTION_UP
6609 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006610 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006611
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006612 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006613 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006614 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6615 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006616
6617 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6618 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006619 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006620 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006621 spy->assertNoEvents();
6622}
6623
6624TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6625 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6626
6627 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6628
6629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6630 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6631 WINDOW_LOCATION));
6632
6633 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6634 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6635 ASSERT_TRUE(consumeSeq);
6636
Prabir Pradhanedd96402022-02-15 01:46:16 -08006637 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006638
6639 monitor.finishEvent(*consumeSeq);
6640 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6641
6642 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006643 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006644}
6645
6646// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6647// process events, you don't get an anr. When the window later becomes unresponsive again, you
6648// get an ANR again.
6649// 1. tap -> block on ACTION_UP -> receive ANR
6650// 2. consume all pending events (= queue becomes healthy again)
6651// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6652TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6653 tapOnWindow();
6654
6655 mWindow->consumeMotionDown();
6656 // Block on ACTION_UP
6657 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006658 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006659 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6660 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006661 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006662 mWindow->assertNoEvents();
6663
6664 tapOnWindow();
6665 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006666 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006667 mWindow->consumeMotionUp();
6668
6669 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006670 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006671 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006672 mWindow->assertNoEvents();
6673}
6674
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006675// If a connection remains unresponsive for a while, make sure policy is only notified once about
6676// it.
6677TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006679 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6680 WINDOW_LOCATION));
6681
6682 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006683 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006684 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006685 // 'notifyConnectionUnresponsive' should only be called once per connection
6686 mFakePolicy->assertNotifyAnrWasNotCalled();
6687 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006688 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006689 mWindow->consumeMotionEvent(
6690 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006691 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006692 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006693 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006694 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006695}
6696
6697/**
6698 * If a window is processing a motion event, and then a key event comes in, the key event should
6699 * not to to the focused window until the motion is processed.
6700 *
6701 * Warning!!!
6702 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6703 * and the injection timeout that we specify when injecting the key.
6704 * We must have the injection timeout (10ms) be smaller than
6705 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6706 *
6707 * If that value changes, this test should also change.
6708 */
6709TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6710 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6712
6713 tapOnWindow();
6714 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6715 ASSERT_TRUE(downSequenceNum);
6716 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6717 ASSERT_TRUE(upSequenceNum);
6718 // Don't finish the events yet, and send a key
6719 // Injection will "succeed" because we will eventually give up and send the key to the focused
6720 // window even if motions are still being processed. But because the injection timeout is short,
6721 // we will receive INJECTION_TIMED_OUT as the result.
6722
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006723 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006724 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006725 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6726 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006727 // Key will not be sent to the window, yet, because the window is still processing events
6728 // and the key remains pending, waiting for the touch events to be processed
6729 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6730 ASSERT_FALSE(keySequenceNum);
6731
6732 std::this_thread::sleep_for(500ms);
6733 // if we wait long enough though, dispatcher will give up, and still send the key
6734 // to the focused window, even though we have not yet finished the motion event
6735 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6736 mWindow->finishEvent(*downSequenceNum);
6737 mWindow->finishEvent(*upSequenceNum);
6738}
6739
6740/**
6741 * If a window is processing a motion event, and then a key event comes in, the key event should
6742 * not go to the focused window until the motion is processed.
6743 * If then a new motion comes in, then the pending key event should be going to the currently
6744 * focused window right away.
6745 */
6746TEST_F(InputDispatcherSingleWindowAnr,
6747 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6748 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6749 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6750
6751 tapOnWindow();
6752 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6753 ASSERT_TRUE(downSequenceNum);
6754 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6755 ASSERT_TRUE(upSequenceNum);
6756 // Don't finish the events yet, and send a key
6757 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006759 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6760 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006761 // At this point, key is still pending, and should not be sent to the application yet.
6762 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6763 ASSERT_FALSE(keySequenceNum);
6764
6765 // Now tap down again. It should cause the pending key to go to the focused window right away.
6766 tapOnWindow();
6767 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6768 // the other events yet. We can finish events in any order.
6769 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6770 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6771 mWindow->consumeMotionDown();
6772 mWindow->consumeMotionUp();
6773 mWindow->assertNoEvents();
6774}
6775
6776class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
6777 virtual void SetUp() override {
6778 InputDispatcherTest::SetUp();
6779
Chris Yea209fde2020-07-22 13:54:51 -07006780 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006781 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006782 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
6783 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006784 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006785 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006786 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006787
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006788 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
6789 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006790 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006791 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006792
6793 // Set focused application.
6794 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07006795 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006796
6797 // Expect one focus window exist in display.
6798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006799 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006800 mFocusedWindow->consumeFocusEvent(true);
6801 }
6802
6803 virtual void TearDown() override {
6804 InputDispatcherTest::TearDown();
6805
6806 mUnfocusedWindow.clear();
6807 mFocusedWindow.clear();
6808 }
6809
6810protected:
Chris Yea209fde2020-07-22 13:54:51 -07006811 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006812 sp<FakeWindowHandle> mUnfocusedWindow;
6813 sp<FakeWindowHandle> mFocusedWindow;
6814 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
6815 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
6816 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
6817
6818 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
6819
6820 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
6821
6822private:
6823 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006825 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6826 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006828 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6829 location));
6830 }
6831};
6832
6833// If we have 2 windows that are both unresponsive, the one with the shortest timeout
6834// should be ANR'd first.
6835TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006837 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6838 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006840 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006841 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006842 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006843 // We consumed all events, so no ANR
6844 ASSERT_TRUE(mDispatcher->waitForIdle());
6845 mFakePolicy->assertNotifyAnrWasNotCalled();
6846
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006848 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6849 FOCUSED_WINDOW_LOCATION));
6850 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
6851 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006852
6853 const std::chrono::duration timeout =
6854 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006855 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006856 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
6857 // sequence to make it consistent
6858 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006860 mFocusedWindow->consumeMotionDown();
6861 // This cancel is generated because the connection was unresponsive
6862 mFocusedWindow->consumeMotionCancel();
6863 mFocusedWindow->assertNoEvents();
6864 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006865 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006866 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6867 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006868 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006869}
6870
6871// If we have 2 windows with identical timeouts that are both unresponsive,
6872// it doesn't matter which order they should have ANR.
6873// But we should receive ANR for both.
6874TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
6875 // Set the timeout for unfocused window to match the focused window
6876 mUnfocusedWindow->setDispatchingTimeout(10ms);
6877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6878
6879 tapOnFocusedWindow();
6880 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08006881 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
6882 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
6883 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884
6885 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006886 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
6887 mFocusedWindow->getToken() == anrConnectionToken2);
6888 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
6889 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006890
6891 ASSERT_TRUE(mDispatcher->waitForIdle());
6892 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006893
6894 mFocusedWindow->consumeMotionDown();
6895 mFocusedWindow->consumeMotionUp();
6896 mUnfocusedWindow->consumeMotionOutside();
6897
Prabir Pradhanedd96402022-02-15 01:46:16 -08006898 sp<IBinder> responsiveToken1, responsiveToken2;
6899 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
6900 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006901
6902 // Both applications should be marked as responsive, in any order
6903 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
6904 mFocusedWindow->getToken() == responsiveToken2);
6905 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
6906 mUnfocusedWindow->getToken() == responsiveToken2);
6907 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006908}
6909
6910// If a window is already not responding, the second tap on the same window should be ignored.
6911// We should also log an error to account for the dropped event (not tested here).
6912// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
6913TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
6914 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006915 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00006916 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006917 // Receive the events, but don't respond
6918 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
6919 ASSERT_TRUE(downEventSequenceNum);
6920 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
6921 ASSERT_TRUE(upEventSequenceNum);
6922 const std::chrono::duration timeout =
6923 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006924 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925
6926 // Tap once again
6927 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006928 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006929 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6930 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006931 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006932 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6933 FOCUSED_WINDOW_LOCATION));
6934 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
6935 // valid touch target
6936 mUnfocusedWindow->assertNoEvents();
6937
6938 // Consume the first tap
6939 mFocusedWindow->finishEvent(*downEventSequenceNum);
6940 mFocusedWindow->finishEvent(*upEventSequenceNum);
6941 ASSERT_TRUE(mDispatcher->waitForIdle());
6942 // The second tap did not go to the focused window
6943 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006944 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08006945 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
6946 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006947 mFakePolicy->assertNotifyAnrWasNotCalled();
6948}
6949
6950// If you tap outside of all windows, there will not be ANR
6951TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006952 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006953 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6954 LOCATION_OUTSIDE_ALL_WINDOWS));
6955 ASSERT_TRUE(mDispatcher->waitForIdle());
6956 mFakePolicy->assertNotifyAnrWasNotCalled();
6957}
6958
6959// Since the focused window is paused, tapping on it should not produce any events
6960TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
6961 mFocusedWindow->setPaused(true);
6962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
6963
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006964 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006965 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6966 FOCUSED_WINDOW_LOCATION));
6967
6968 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
6969 ASSERT_TRUE(mDispatcher->waitForIdle());
6970 // Should not ANR because the window is paused, and touches shouldn't go to it
6971 mFakePolicy->assertNotifyAnrWasNotCalled();
6972
6973 mFocusedWindow->assertNoEvents();
6974 mUnfocusedWindow->assertNoEvents();
6975}
6976
6977/**
6978 * If a window is processing a motion event, and then a key event comes in, the key event should
6979 * not to to the focused window until the motion is processed.
6980 * If a different window becomes focused at this time, the key should go to that window instead.
6981 *
6982 * Warning!!!
6983 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6984 * and the injection timeout that we specify when injecting the key.
6985 * We must have the injection timeout (10ms) be smaller than
6986 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6987 *
6988 * If that value changes, this test should also change.
6989 */
6990TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
6991 // Set a long ANR timeout to prevent it from triggering
6992 mFocusedWindow->setDispatchingTimeout(2s);
6993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
6994
6995 tapOnUnfocusedWindow();
6996 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
6997 ASSERT_TRUE(downSequenceNum);
6998 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
6999 ASSERT_TRUE(upSequenceNum);
7000 // Don't finish the events yet, and send a key
7001 // Injection will succeed because we will eventually give up and send the key to the focused
7002 // window even if motions are still being processed.
7003
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007004 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007005 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7006 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007008 // Key will not be sent to the window, yet, because the window is still processing events
7009 // and the key remains pending, waiting for the touch events to be processed
7010 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7011 ASSERT_FALSE(keySequenceNum);
7012
7013 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007014 mFocusedWindow->setFocusable(false);
7015 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007017 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007018
7019 // Focus events should precede the key events
7020 mUnfocusedWindow->consumeFocusEvent(true);
7021 mFocusedWindow->consumeFocusEvent(false);
7022
7023 // Finish the tap events, which should unblock dispatcher
7024 mUnfocusedWindow->finishEvent(*downSequenceNum);
7025 mUnfocusedWindow->finishEvent(*upSequenceNum);
7026
7027 // Now that all queues are cleared and no backlog in the connections, the key event
7028 // can finally go to the newly focused "mUnfocusedWindow".
7029 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7030 mFocusedWindow->assertNoEvents();
7031 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007032 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007033}
7034
7035// When the touch stream is split across 2 windows, and one of them does not respond,
7036// then ANR should be raised and the touch should be canceled for the unresponsive window.
7037// The other window should not be affected by that.
7038TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7039 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007040 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7041 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7042 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007043 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007044 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007045
7046 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007047 mDispatcher->notifyMotion(
7048 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7049 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007050
7051 const std::chrono::duration timeout =
7052 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007053 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007054
7055 mUnfocusedWindow->consumeMotionDown();
7056 mFocusedWindow->consumeMotionDown();
7057 // Focused window may or may not receive ACTION_MOVE
7058 // But it should definitely receive ACTION_CANCEL due to the ANR
7059 InputEvent* event;
7060 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7061 ASSERT_TRUE(moveOrCancelSequenceNum);
7062 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7063 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007064 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007065 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7066 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7067 mFocusedWindow->consumeMotionCancel();
7068 } else {
7069 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7070 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007071 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007072 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7073 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007074
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007075 mUnfocusedWindow->assertNoEvents();
7076 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007077 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007078}
7079
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007080/**
7081 * If we have no focused window, and a key comes in, we start the ANR timer.
7082 * The focused application should add a focused window before the timer runs out to prevent ANR.
7083 *
7084 * If the user touches another application during this time, the key should be dropped.
7085 * Next, if a new focused window comes in, without toggling the focused application,
7086 * then no ANR should occur.
7087 *
7088 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7089 * but in some cases the policy may not update the focused application.
7090 */
7091TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7092 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7093 std::make_shared<FakeApplicationHandle>();
7094 focusedApplication->setDispatchingTimeout(60ms);
7095 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7096 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7097 mFocusedWindow->setFocusable(false);
7098
7099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7100 mFocusedWindow->consumeFocusEvent(false);
7101
7102 // Send a key. The ANR timer should start because there is no focused window.
7103 // 'focusedApplication' will get blamed if this timer completes.
7104 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007105 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007106 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7107 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7108 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007110
7111 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7112 // then the injected touches won't cause the focused event to get dropped.
7113 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7114 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7115 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7116 // For this test, it means that the key would get delivered to the window once it becomes
7117 // focused.
7118 std::this_thread::sleep_for(10ms);
7119
7120 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007121 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7122 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7123 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007124
7125 // We do not consume the motion right away, because that would require dispatcher to first
7126 // process (== drop) the key event, and by that time, ANR will be raised.
7127 // Set the focused window first.
7128 mFocusedWindow->setFocusable(true);
7129 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7130 setFocusedWindow(mFocusedWindow);
7131 mFocusedWindow->consumeFocusEvent(true);
7132 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7133 // to another application. This could be a bug / behaviour in the policy.
7134
7135 mUnfocusedWindow->consumeMotionDown();
7136
7137 ASSERT_TRUE(mDispatcher->waitForIdle());
7138 // Should not ANR because we actually have a focused window. It was just added too slowly.
7139 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7140}
7141
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007142// These tests ensure we cannot send touch events to a window that's positioned behind a window
7143// that has feature NO_INPUT_CHANNEL.
7144// Layout:
7145// Top (closest to user)
7146// mNoInputWindow (above all windows)
7147// mBottomWindow
7148// Bottom (furthest from user)
7149class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7150 virtual void SetUp() override {
7151 InputDispatcherTest::SetUp();
7152
7153 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007154 mNoInputWindow =
7155 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7156 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007157 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007158 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007159 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7160 // It's perfectly valid for this window to not have an associated input channel
7161
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007162 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7163 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007164 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7165
7166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7167 }
7168
7169protected:
7170 std::shared_ptr<FakeApplicationHandle> mApplication;
7171 sp<FakeWindowHandle> mNoInputWindow;
7172 sp<FakeWindowHandle> mBottomWindow;
7173};
7174
7175TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7176 PointF touchedPoint = {10, 10};
7177
Prabir Pradhan678438e2023-04-13 19:32:51 +00007178 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7179 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7180 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007181
7182 mNoInputWindow->assertNoEvents();
7183 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7184 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7185 // and therefore should prevent mBottomWindow from receiving touches
7186 mBottomWindow->assertNoEvents();
7187}
7188
7189/**
7190 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7191 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7192 */
7193TEST_F(InputDispatcherMultiWindowOcclusionTests,
7194 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007195 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7196 "Window with input channel and NO_INPUT_CHANNEL",
7197 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007198
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007199 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007200 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7202
7203 PointF touchedPoint = {10, 10};
7204
Prabir Pradhan678438e2023-04-13 19:32:51 +00007205 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7206 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7207 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007208
7209 mNoInputWindow->assertNoEvents();
7210 mBottomWindow->assertNoEvents();
7211}
7212
Vishnu Nair958da932020-08-21 17:12:37 -07007213class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7214protected:
7215 std::shared_ptr<FakeApplicationHandle> mApp;
7216 sp<FakeWindowHandle> mWindow;
7217 sp<FakeWindowHandle> mMirror;
7218
7219 virtual void SetUp() override {
7220 InputDispatcherTest::SetUp();
7221 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007222 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7223 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7224 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007225 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7226 mWindow->setFocusable(true);
7227 mMirror->setFocusable(true);
7228 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7229 }
7230};
7231
7232TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7233 // Request focus on a mirrored window
7234 setFocusedWindow(mMirror);
7235
7236 // window gets focused
7237 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7239 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007240 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7241}
7242
7243// A focused & mirrored window remains focused only if the window and its mirror are both
7244// focusable.
7245TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7246 setFocusedWindow(mMirror);
7247
7248 // window gets focused
7249 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7251 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007252 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7254 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007255 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7256
7257 mMirror->setFocusable(false);
7258 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7259
7260 // window loses focus since one of the windows associated with the token in not focusable
7261 mWindow->consumeFocusEvent(false);
7262
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7264 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007265 mWindow->assertNoEvents();
7266}
7267
7268// A focused & mirrored window remains focused until the window and its mirror both become
7269// invisible.
7270TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7271 setFocusedWindow(mMirror);
7272
7273 // window gets focused
7274 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7276 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007277 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7279 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007280 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7281
7282 mMirror->setVisible(false);
7283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7284
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7286 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007287 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7289 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007290 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7291
7292 mWindow->setVisible(false);
7293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7294
7295 // window loses focus only after all windows associated with the token become invisible.
7296 mWindow->consumeFocusEvent(false);
7297
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007298 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7299 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007300 mWindow->assertNoEvents();
7301}
7302
7303// A focused & mirrored window remains focused until both windows are removed.
7304TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7305 setFocusedWindow(mMirror);
7306
7307 // window gets focused
7308 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7310 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007311 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7313 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007314 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7315
7316 // single window is removed but the window token remains focused
7317 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7318
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007319 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7320 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007321 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7323 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007324 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7325
7326 // Both windows are removed
7327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7328 mWindow->consumeFocusEvent(false);
7329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007330 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7331 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007332 mWindow->assertNoEvents();
7333}
7334
7335// Focus request can be pending until one window becomes visible.
7336TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7337 // Request focus on an invisible mirror.
7338 mWindow->setVisible(false);
7339 mMirror->setVisible(false);
7340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7341 setFocusedWindow(mMirror);
7342
7343 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007345 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7346 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007347
7348 mMirror->setVisible(true);
7349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7350
7351 // window gets focused
7352 mWindow->consumeFocusEvent(true);
7353 // window gets the pending key event
7354 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7355}
Prabir Pradhan99987712020-11-10 18:43:05 -08007356
7357class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7358protected:
7359 std::shared_ptr<FakeApplicationHandle> mApp;
7360 sp<FakeWindowHandle> mWindow;
7361 sp<FakeWindowHandle> mSecondWindow;
7362
7363 void SetUp() override {
7364 InputDispatcherTest::SetUp();
7365 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007366 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007367 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007368 mSecondWindow =
7369 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007370 mSecondWindow->setFocusable(true);
7371
7372 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7374
7375 setFocusedWindow(mWindow);
7376 mWindow->consumeFocusEvent(true);
7377 }
7378
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007379 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007380 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007381 }
7382
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007383 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7384 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007385 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007386 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7387 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007388 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007389 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007390 }
7391};
7392
7393TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7394 // Ensure that capture cannot be obtained for unfocused windows.
7395 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7396 mFakePolicy->assertSetPointerCaptureNotCalled();
7397 mSecondWindow->assertNoEvents();
7398
7399 // Ensure that capture can be enabled from the focus window.
7400 requestAndVerifyPointerCapture(mWindow, true);
7401
7402 // Ensure that capture cannot be disabled from a window that does not have capture.
7403 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7404 mFakePolicy->assertSetPointerCaptureNotCalled();
7405
7406 // Ensure that capture can be disabled from the window with capture.
7407 requestAndVerifyPointerCapture(mWindow, false);
7408}
7409
7410TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007411 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007412
7413 setFocusedWindow(mSecondWindow);
7414
7415 // Ensure that the capture disabled event was sent first.
7416 mWindow->consumeCaptureEvent(false);
7417 mWindow->consumeFocusEvent(false);
7418 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007419 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007420
7421 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007422 notifyPointerCaptureChanged({});
7423 notifyPointerCaptureChanged(request);
7424 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007425 mWindow->assertNoEvents();
7426 mSecondWindow->assertNoEvents();
7427 mFakePolicy->assertSetPointerCaptureNotCalled();
7428}
7429
7430TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007431 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007432
7433 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007434 notifyPointerCaptureChanged({});
7435 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007436
7437 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007438 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007439 mWindow->consumeCaptureEvent(false);
7440 mWindow->assertNoEvents();
7441}
7442
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007443TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7444 requestAndVerifyPointerCapture(mWindow, true);
7445
7446 // The first window loses focus.
7447 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007448 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007449 mWindow->consumeCaptureEvent(false);
7450
7451 // Request Pointer Capture from the second window before the notification from InputReader
7452 // arrives.
7453 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007454 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007455
7456 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007457 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007458
7459 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007460 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007461
7462 mSecondWindow->consumeFocusEvent(true);
7463 mSecondWindow->consumeCaptureEvent(true);
7464}
7465
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007466TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7467 // App repeatedly enables and disables capture.
7468 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7469 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7470 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7471 mFakePolicy->assertSetPointerCaptureCalled(false);
7472 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7473 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7474
7475 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7476 // first request is now stale, this should do nothing.
7477 notifyPointerCaptureChanged(firstRequest);
7478 mWindow->assertNoEvents();
7479
7480 // InputReader notifies that the second request was enabled.
7481 notifyPointerCaptureChanged(secondRequest);
7482 mWindow->consumeCaptureEvent(true);
7483}
7484
Prabir Pradhan7092e262022-05-03 16:51:09 +00007485TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7486 requestAndVerifyPointerCapture(mWindow, true);
7487
7488 // App toggles pointer capture off and on.
7489 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7490 mFakePolicy->assertSetPointerCaptureCalled(false);
7491
7492 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7493 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7494
7495 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7496 // preceding "disable" request.
7497 notifyPointerCaptureChanged(enableRequest);
7498
7499 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7500 // any notifications.
7501 mWindow->assertNoEvents();
7502}
7503
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007504class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7505protected:
7506 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007507
7508 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7509 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7510
7511 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7512 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7513
7514 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7515 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7516 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7517 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7518 MAXIMUM_OBSCURING_OPACITY);
7519
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007520 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007521 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007522 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007523
7524 sp<FakeWindowHandle> mTouchWindow;
7525
7526 virtual void SetUp() override {
7527 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007528 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007529 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7530 }
7531
7532 virtual void TearDown() override {
7533 InputDispatcherTest::TearDown();
7534 mTouchWindow.clear();
7535 }
7536
chaviw3277faf2021-05-19 16:45:23 -05007537 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7538 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007539 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007540 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007541 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007542 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007543 return window;
7544 }
7545
7546 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7547 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7548 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007549 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007550 // Generate an arbitrary PID based on the UID
7551 window->setOwnerInfo(1777 + (uid % 10000), uid);
7552 return window;
7553 }
7554
7555 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7558 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007559 }
7560};
7561
7562TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007563 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007564 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007566
7567 touch();
7568
7569 mTouchWindow->assertNoEvents();
7570}
7571
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007572TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007573 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7574 const sp<FakeWindowHandle>& w =
7575 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7576 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7577
7578 touch();
7579
7580 mTouchWindow->assertNoEvents();
7581}
7582
7583TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007584 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7585 const sp<FakeWindowHandle>& w =
7586 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7588
7589 touch();
7590
7591 w->assertNoEvents();
7592}
7593
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007594TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007595 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007597
7598 touch();
7599
7600 mTouchWindow->consumeAnyMotionDown();
7601}
7602
7603TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007604 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007605 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007606 w->setFrame(Rect(0, 0, 50, 50));
7607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007608
7609 touch({PointF{100, 100}});
7610
7611 mTouchWindow->consumeAnyMotionDown();
7612}
7613
7614TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007615 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007616 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7618
7619 touch();
7620
7621 mTouchWindow->consumeAnyMotionDown();
7622}
7623
7624TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7625 const sp<FakeWindowHandle>& w =
7626 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007628
7629 touch();
7630
7631 mTouchWindow->consumeAnyMotionDown();
7632}
7633
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007634TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7635 const sp<FakeWindowHandle>& w =
7636 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7638
7639 touch();
7640
7641 w->assertNoEvents();
7642}
7643
7644/**
7645 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7646 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7647 * window, the occluding window will still receive ACTION_OUTSIDE event.
7648 */
7649TEST_F(InputDispatcherUntrustedTouchesTest,
7650 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7651 const sp<FakeWindowHandle>& w =
7652 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007653 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7655
7656 touch();
7657
7658 w->consumeMotionOutside();
7659}
7660
7661TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7662 const sp<FakeWindowHandle>& w =
7663 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007664 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007665 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7666
7667 touch();
7668
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007669 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007670}
7671
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007672TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007673 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007674 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7675 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7677
7678 touch();
7679
7680 mTouchWindow->consumeAnyMotionDown();
7681}
7682
7683TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7684 const sp<FakeWindowHandle>& w =
7685 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7686 MAXIMUM_OBSCURING_OPACITY);
7687 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007688
7689 touch();
7690
7691 mTouchWindow->consumeAnyMotionDown();
7692}
7693
7694TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007695 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007696 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7697 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7699
7700 touch();
7701
7702 mTouchWindow->assertNoEvents();
7703}
7704
7705TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7706 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7707 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007708 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7709 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007710 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007711 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7712 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7714
7715 touch();
7716
7717 mTouchWindow->assertNoEvents();
7718}
7719
7720TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7721 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7722 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007723 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7724 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007725 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007726 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7727 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007728 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7729
7730 touch();
7731
7732 mTouchWindow->consumeAnyMotionDown();
7733}
7734
7735TEST_F(InputDispatcherUntrustedTouchesTest,
7736 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7737 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007738 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7739 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007740 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007741 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7742 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007743 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7744
7745 touch();
7746
7747 mTouchWindow->consumeAnyMotionDown();
7748}
7749
7750TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7751 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007752 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7753 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007754 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007755 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7756 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007757 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007758
7759 touch();
7760
7761 mTouchWindow->assertNoEvents();
7762}
7763
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007764TEST_F(InputDispatcherUntrustedTouchesTest,
7765 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7766 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007767 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7768 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007769 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007770 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7771 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007772 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7773
7774 touch();
7775
7776 mTouchWindow->assertNoEvents();
7777}
7778
7779TEST_F(InputDispatcherUntrustedTouchesTest,
7780 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
7781 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007782 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7783 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007784 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007785 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7786 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7788
7789 touch();
7790
7791 mTouchWindow->consumeAnyMotionDown();
7792}
7793
7794TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
7795 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007796 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7797 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7799
7800 touch();
7801
7802 mTouchWindow->consumeAnyMotionDown();
7803}
7804
7805TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
7806 const sp<FakeWindowHandle>& w =
7807 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
7808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7809
7810 touch();
7811
7812 mTouchWindow->consumeAnyMotionDown();
7813}
7814
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007815TEST_F(InputDispatcherUntrustedTouchesTest,
7816 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
7817 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7818 const sp<FakeWindowHandle>& w =
7819 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
7820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7821
7822 touch();
7823
7824 mTouchWindow->assertNoEvents();
7825}
7826
7827TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
7828 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
7829 const sp<FakeWindowHandle>& w =
7830 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
7831 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7832
7833 touch();
7834
7835 mTouchWindow->consumeAnyMotionDown();
7836}
7837
7838TEST_F(InputDispatcherUntrustedTouchesTest,
7839 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
7840 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
7841 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007842 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7843 OPACITY_ABOVE_THRESHOLD);
7844 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7845
7846 touch();
7847
7848 mTouchWindow->consumeAnyMotionDown();
7849}
7850
7851TEST_F(InputDispatcherUntrustedTouchesTest,
7852 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
7853 const sp<FakeWindowHandle>& w1 =
7854 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7855 OPACITY_BELOW_THRESHOLD);
7856 const sp<FakeWindowHandle>& w2 =
7857 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7858 OPACITY_BELOW_THRESHOLD);
7859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7860
7861 touch();
7862
7863 mTouchWindow->assertNoEvents();
7864}
7865
7866/**
7867 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
7868 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
7869 * (which alone would result in allowing touches) does not affect the blocking behavior.
7870 */
7871TEST_F(InputDispatcherUntrustedTouchesTest,
7872 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
7873 const sp<FakeWindowHandle>& wB =
7874 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
7875 OPACITY_BELOW_THRESHOLD);
7876 const sp<FakeWindowHandle>& wC =
7877 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7878 OPACITY_BELOW_THRESHOLD);
7879 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7880
7881 touch();
7882
7883 mTouchWindow->assertNoEvents();
7884}
7885
7886/**
7887 * This test is testing that a window from a different UID but with same application token doesn't
7888 * block the touch. Apps can share the application token for close UI collaboration for example.
7889 */
7890TEST_F(InputDispatcherUntrustedTouchesTest,
7891 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
7892 const sp<FakeWindowHandle>& w =
7893 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7894 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00007895 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7896
7897 touch();
7898
7899 mTouchWindow->consumeAnyMotionDown();
7900}
7901
arthurhungb89ccb02020-12-30 16:19:01 +08007902class InputDispatcherDragTests : public InputDispatcherTest {
7903protected:
7904 std::shared_ptr<FakeApplicationHandle> mApp;
7905 sp<FakeWindowHandle> mWindow;
7906 sp<FakeWindowHandle> mSecondWindow;
7907 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007908 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007909 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
7910 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08007911
7912 void SetUp() override {
7913 InputDispatcherTest::SetUp();
7914 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007915 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007916 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007917
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007918 mSecondWindow =
7919 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08007920 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08007921
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007922 mSpyWindow =
7923 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007924 mSpyWindow->setSpy(true);
7925 mSpyWindow->setTrustedOverlay(true);
7926 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
7927
arthurhungb89ccb02020-12-30 16:19:01 +08007928 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007930 }
7931
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007932 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
7933 switch (fromSource) {
7934 case AINPUT_SOURCE_TOUCHSCREEN:
7935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7936 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7937 ADISPLAY_ID_DEFAULT, {50, 50}))
7938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7939 break;
7940 case AINPUT_SOURCE_STYLUS:
7941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7942 injectMotionEvent(
7943 mDispatcher,
7944 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
7945 AINPUT_SOURCE_STYLUS)
7946 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007947 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007948 .x(50)
7949 .y(50))
7950 .build()));
7951 break;
7952 case AINPUT_SOURCE_MOUSE:
7953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7954 injectMotionEvent(
7955 mDispatcher,
7956 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7957 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
7958 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007959 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007960 .x(50)
7961 .y(50))
7962 .build()));
7963 break;
7964 default:
7965 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
7966 }
arthurhungb89ccb02020-12-30 16:19:01 +08007967
7968 // Window should receive motion event.
7969 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007970 // Spy window should also receive motion event
7971 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00007972 }
7973
7974 // Start performing drag, we will create a drag window and transfer touch to it.
7975 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
7976 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007977 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00007978 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00007979 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00007980 }
arthurhungb89ccb02020-12-30 16:19:01 +08007981
7982 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007983 mDragWindow =
7984 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007985 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08007986 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00007987 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08007988
7989 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00007990 bool transferred =
7991 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00007992 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00007993 if (transferred) {
7994 mWindow->consumeMotionCancel();
7995 mDragWindow->consumeMotionDown();
7996 }
7997 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08007998 }
7999};
8000
8001TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008002 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008003
8004 // Move on window.
8005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8006 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8007 ADISPLAY_ID_DEFAULT, {50, 50}))
8008 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8009 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8010 mWindow->consumeDragEvent(false, 50, 50);
8011 mSecondWindow->assertNoEvents();
8012
8013 // Move to another window.
8014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8015 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8016 ADISPLAY_ID_DEFAULT, {150, 50}))
8017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8018 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8019 mWindow->consumeDragEvent(true, 150, 50);
8020 mSecondWindow->consumeDragEvent(false, 50, 50);
8021
8022 // Move back to original window.
8023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8024 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8025 ADISPLAY_ID_DEFAULT, {50, 50}))
8026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8027 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8028 mWindow->consumeDragEvent(false, 50, 50);
8029 mSecondWindow->consumeDragEvent(true, -50, 50);
8030
8031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8032 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8034 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8035 mWindow->assertNoEvents();
8036 mSecondWindow->assertNoEvents();
8037}
8038
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008039TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008040 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008041
8042 // No cancel event after drag start
8043 mSpyWindow->assertNoEvents();
8044
8045 const MotionEvent secondFingerDownEvent =
8046 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8047 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008048 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8049 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008050 .build();
8051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8052 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8053 InputEventInjectionSync::WAIT_FOR_RESULT))
8054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8055
8056 // Receives cancel for first pointer after next pointer down
8057 mSpyWindow->consumeMotionCancel();
8058 mSpyWindow->consumeMotionDown();
8059
8060 mSpyWindow->assertNoEvents();
8061}
8062
arthurhungf452d0b2021-01-06 00:19:52 +08008063TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008064 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008065
8066 // Move on window.
8067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8068 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8069 ADISPLAY_ID_DEFAULT, {50, 50}))
8070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8071 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8072 mWindow->consumeDragEvent(false, 50, 50);
8073 mSecondWindow->assertNoEvents();
8074
8075 // Move to another window.
8076 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8077 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8078 ADISPLAY_ID_DEFAULT, {150, 50}))
8079 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8080 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8081 mWindow->consumeDragEvent(true, 150, 50);
8082 mSecondWindow->consumeDragEvent(false, 50, 50);
8083
8084 // drop to another window.
8085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8086 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8087 {150, 50}))
8088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8089 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8090 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8091 mWindow->assertNoEvents();
8092 mSecondWindow->assertNoEvents();
8093}
8094
arthurhung6d4bed92021-03-17 11:59:33 +08008095TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008096 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008097
8098 // Move on window and keep button pressed.
8099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8100 injectMotionEvent(mDispatcher,
8101 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8102 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008103 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008104 .build()))
8105 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8106 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8107 mWindow->consumeDragEvent(false, 50, 50);
8108 mSecondWindow->assertNoEvents();
8109
8110 // Move to another window and release button, expect to drop item.
8111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8112 injectMotionEvent(mDispatcher,
8113 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8114 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008115 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008116 .build()))
8117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8118 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8119 mWindow->assertNoEvents();
8120 mSecondWindow->assertNoEvents();
8121 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8122
8123 // nothing to the window.
8124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8125 injectMotionEvent(mDispatcher,
8126 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8127 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008128 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008129 .build()))
8130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8131 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8132 mWindow->assertNoEvents();
8133 mSecondWindow->assertNoEvents();
8134}
8135
Arthur Hung54745652022-04-20 07:17:41 +00008136TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008137 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008138
8139 // Set second window invisible.
8140 mSecondWindow->setVisible(false);
8141 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8142
8143 // Move on window.
8144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8145 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8146 ADISPLAY_ID_DEFAULT, {50, 50}))
8147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8148 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8149 mWindow->consumeDragEvent(false, 50, 50);
8150 mSecondWindow->assertNoEvents();
8151
8152 // Move to another window.
8153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8154 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8155 ADISPLAY_ID_DEFAULT, {150, 50}))
8156 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8157 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8158 mWindow->consumeDragEvent(true, 150, 50);
8159 mSecondWindow->assertNoEvents();
8160
8161 // drop to another window.
8162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8163 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8164 {150, 50}))
8165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8166 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8167 mFakePolicy->assertDropTargetEquals(nullptr);
8168 mWindow->assertNoEvents();
8169 mSecondWindow->assertNoEvents();
8170}
8171
Arthur Hung54745652022-04-20 07:17:41 +00008172TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008173 // Ensure window could track pointerIds if it didn't support split touch.
8174 mWindow->setPreventSplitting(true);
8175
Arthur Hung54745652022-04-20 07:17:41 +00008176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8177 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8178 {50, 50}))
8179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8180 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8181
8182 const MotionEvent secondFingerDownEvent =
8183 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8184 .displayId(ADISPLAY_ID_DEFAULT)
8185 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008186 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8187 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008188 .build();
8189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8190 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8191 InputEventInjectionSync::WAIT_FOR_RESULT))
8192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008193 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008194
8195 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008196 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008197}
8198
8199TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8200 // First down on second window.
8201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8202 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8203 {150, 50}))
8204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8205
8206 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8207
8208 // Second down on first window.
8209 const MotionEvent secondFingerDownEvent =
8210 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8211 .displayId(ADISPLAY_ID_DEFAULT)
8212 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008213 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8214 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008215 .build();
8216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8217 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8218 InputEventInjectionSync::WAIT_FOR_RESULT))
8219 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8220 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8221
8222 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008223 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008224
8225 // Move on window.
8226 const MotionEvent secondFingerMoveEvent =
8227 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8228 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008229 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8230 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008231 .build();
8232 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8233 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8234 InputEventInjectionSync::WAIT_FOR_RESULT));
8235 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8236 mWindow->consumeDragEvent(false, 50, 50);
8237 mSecondWindow->consumeMotionMove();
8238
8239 // Release the drag pointer should perform drop.
8240 const MotionEvent secondFingerUpEvent =
8241 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8242 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008243 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8244 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008245 .build();
8246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8247 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8248 InputEventInjectionSync::WAIT_FOR_RESULT));
8249 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8250 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8251 mWindow->assertNoEvents();
8252 mSecondWindow->consumeMotionMove();
8253}
8254
Arthur Hung3915c1f2022-05-31 07:17:17 +00008255TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008256 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008257
8258 // Update window of second display.
8259 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008260 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008261 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8262
8263 // Let second display has a touch state.
8264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8265 injectMotionEvent(mDispatcher,
8266 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8267 AINPUT_SOURCE_TOUCHSCREEN)
8268 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008269 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008270 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008271 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008272 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008273 // Update window again.
8274 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8275
8276 // Move on window.
8277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8278 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8279 ADISPLAY_ID_DEFAULT, {50, 50}))
8280 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8281 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8282 mWindow->consumeDragEvent(false, 50, 50);
8283 mSecondWindow->assertNoEvents();
8284
8285 // Move to another window.
8286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8287 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8288 ADISPLAY_ID_DEFAULT, {150, 50}))
8289 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8290 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8291 mWindow->consumeDragEvent(true, 150, 50);
8292 mSecondWindow->consumeDragEvent(false, 50, 50);
8293
8294 // drop to another window.
8295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8296 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8297 {150, 50}))
8298 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8299 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8300 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8301 mWindow->assertNoEvents();
8302 mSecondWindow->assertNoEvents();
8303}
8304
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008305TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8306 startDrag(true, AINPUT_SOURCE_MOUSE);
8307 // Move on window.
8308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8309 injectMotionEvent(mDispatcher,
8310 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8311 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8312 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008313 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008314 .x(50)
8315 .y(50))
8316 .build()))
8317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8318 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8319 mWindow->consumeDragEvent(false, 50, 50);
8320 mSecondWindow->assertNoEvents();
8321
8322 // Move to another window.
8323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8324 injectMotionEvent(mDispatcher,
8325 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8326 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8327 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008328 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008329 .x(150)
8330 .y(50))
8331 .build()))
8332 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8333 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8334 mWindow->consumeDragEvent(true, 150, 50);
8335 mSecondWindow->consumeDragEvent(false, 50, 50);
8336
8337 // drop to another window.
8338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8339 injectMotionEvent(mDispatcher,
8340 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8341 .buttonState(0)
8342 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008343 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008344 .x(150)
8345 .y(50))
8346 .build()))
8347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8348 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8349 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8350 mWindow->assertNoEvents();
8351 mSecondWindow->assertNoEvents();
8352}
8353
Vishnu Nair062a8672021-09-03 16:07:44 -07008354class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8355
8356TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8357 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008358 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8359 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008360 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008361 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8362 window->setFocusable(true);
8363 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8364 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008365 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008366
8367 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008368 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008369 window->assertNoEvents();
8370
Prabir Pradhan678438e2023-04-13 19:32:51 +00008371 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8372 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008373 window->assertNoEvents();
8374
8375 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008376 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008377 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8378
Prabir Pradhan678438e2023-04-13 19:32:51 +00008379 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008380 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8381
Prabir Pradhan678438e2023-04-13 19:32:51 +00008382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8383 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008384 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8385 window->assertNoEvents();
8386}
8387
8388TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8389 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8390 std::make_shared<FakeApplicationHandle>();
8391 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008392 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8393 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008394 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8395 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008396 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008398 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8399 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008400 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008401 window->setOwnerInfo(222, 222);
8402 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8403 window->setFocusable(true);
8404 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8405 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008406 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008407
8408 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008409 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008410 window->assertNoEvents();
8411
Prabir Pradhan678438e2023-04-13 19:32:51 +00008412 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8413 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008414 window->assertNoEvents();
8415
8416 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008417 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8419
Prabir Pradhan678438e2023-04-13 19:32:51 +00008420 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008421 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8422
Prabir Pradhan678438e2023-04-13 19:32:51 +00008423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8424 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008425 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8426 window->assertNoEvents();
8427}
8428
8429TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8430 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8431 std::make_shared<FakeApplicationHandle>();
8432 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008433 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8434 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008435 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8436 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008437 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008439 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8440 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008441 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008442 window->setOwnerInfo(222, 222);
8443 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8444 window->setFocusable(true);
8445 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8446 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008447 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008448
8449 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008450 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008451 window->assertNoEvents();
8452
Prabir Pradhan678438e2023-04-13 19:32:51 +00008453 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8454 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008455 window->assertNoEvents();
8456
8457 // When the window is no longer obscured because it went on top, it should get input
8458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8459
Prabir Pradhan678438e2023-04-13 19:32:51 +00008460 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008461 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8462
Prabir Pradhan678438e2023-04-13 19:32:51 +00008463 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8464 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008465 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8466 window->assertNoEvents();
8467}
8468
Antonio Kantekf16f2832021-09-28 04:39:20 +00008469class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8470protected:
8471 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008472 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008473 sp<FakeWindowHandle> mWindow;
8474 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008475 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008476
8477 void SetUp() override {
8478 InputDispatcherTest::SetUp();
8479
8480 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008481 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008482 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008483 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008484 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008485 mSecondWindow =
8486 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008487 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008488 mThirdWindow =
8489 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8490 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8491 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008492
8493 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8495 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8496 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008497 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008498
Antonio Kantek15beb512022-06-13 22:35:41 +00008499 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008500 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008501 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008502 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8503 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008504 mThirdWindow->assertNoEvents();
8505 }
8506
8507 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8508 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008509 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008510 SECOND_DISPLAY_ID)) {
8511 mWindow->assertNoEvents();
8512 mSecondWindow->assertNoEvents();
8513 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008514 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008515 }
8516
Antonio Kantek15beb512022-06-13 22:35:41 +00008517 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8518 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008519 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8520 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008521 mWindow->consumeTouchModeEvent(inTouchMode);
8522 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008523 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008524 }
8525};
8526
Antonio Kantek26defcf2022-02-08 01:12:27 +00008527TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008528 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008529 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8530 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008531 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008532}
8533
Antonio Kantek26defcf2022-02-08 01:12:27 +00008534TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8535 const WindowInfo& windowInfo = *mWindow->getInfo();
8536 int32_t ownerPid = windowInfo.ownerPid;
8537 int32_t ownerUid = windowInfo.ownerUid;
8538 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8539 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008540 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008541 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008542 mWindow->assertNoEvents();
8543 mSecondWindow->assertNoEvents();
8544}
8545
8546TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8547 const WindowInfo& windowInfo = *mWindow->getInfo();
8548 int32_t ownerPid = windowInfo.ownerPid;
8549 int32_t ownerUid = windowInfo.ownerUid;
8550 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008551 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008552 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008553}
8554
Antonio Kantekf16f2832021-09-28 04:39:20 +00008555TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008556 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008557 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8558 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008559 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008560 mWindow->assertNoEvents();
8561 mSecondWindow->assertNoEvents();
8562}
8563
Antonio Kantek15beb512022-06-13 22:35:41 +00008564TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8565 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8566 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8567 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008568 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008569 mWindow->assertNoEvents();
8570 mSecondWindow->assertNoEvents();
8571 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8572}
8573
Antonio Kantek48710e42022-03-24 14:19:30 -07008574TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8575 // Interact with the window first.
8576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8577 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8578 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8579
8580 // Then remove focus.
8581 mWindow->setFocusable(false);
8582 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8583
8584 // Assert that caller can switch touch mode by owning one of the last interacted window.
8585 const WindowInfo& windowInfo = *mWindow->getInfo();
8586 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8587 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008588 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008589}
8590
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008591class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8592public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008593 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008594 std::shared_ptr<FakeApplicationHandle> application =
8595 std::make_shared<FakeApplicationHandle>();
8596 std::string name = "Fake Spy ";
8597 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008598 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8599 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008600 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008601 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008602 return spy;
8603 }
8604
8605 sp<FakeWindowHandle> createForeground() {
8606 std::shared_ptr<FakeApplicationHandle> application =
8607 std::make_shared<FakeApplicationHandle>();
8608 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008609 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8610 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008611 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008612 return window;
8613 }
8614
8615private:
8616 int mSpyCount{0};
8617};
8618
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008619using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008620/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008621 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8622 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008623TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8624 ScopedSilentDeath _silentDeath;
8625
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008626 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008627 spy->setTrustedOverlay(false);
8628 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8629 ".* not a trusted overlay");
8630}
8631
8632/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008633 * Input injection into a display with a spy window but no foreground windows should succeed.
8634 */
8635TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008636 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008637 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8638
8639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8640 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8642 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8643}
8644
8645/**
8646 * Verify the order in which different input windows receive events. The touched foreground window
8647 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8648 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8649 * receive events before ones belows it.
8650 *
8651 * Here, we set up a scenario with four windows in the following Z order from the top:
8652 * spy1, spy2, window, spy3.
8653 * We then inject an event and verify that the foreground "window" receives it first, followed by
8654 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8655 * window.
8656 */
8657TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8658 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008659 auto spy1 = createSpy();
8660 auto spy2 = createSpy();
8661 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8663 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8664 const size_t numChannels = channels.size();
8665
Michael Wright8e9a8562022-02-09 13:44:29 +00008666 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008667 if (!epollFd.ok()) {
8668 FAIL() << "Failed to create epoll fd";
8669 }
8670
8671 for (size_t i = 0; i < numChannels; i++) {
8672 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8673 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8674 FAIL() << "Failed to add fd to epoll";
8675 }
8676 }
8677
8678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8679 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8681
8682 std::vector<size_t> eventOrder;
8683 std::vector<struct epoll_event> events(numChannels);
8684 for (;;) {
8685 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8686 (100ms).count());
8687 if (nFds < 0) {
8688 FAIL() << "Failed to call epoll_wait";
8689 }
8690 if (nFds == 0) {
8691 break; // epoll_wait timed out
8692 }
8693 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008694 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008695 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008696 channels[i]->consumeMotionDown();
8697 }
8698 }
8699
8700 // Verify the order in which the events were received.
8701 EXPECT_EQ(3u, eventOrder.size());
8702 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8703 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8704 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8705}
8706
8707/**
8708 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8709 */
8710TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8711 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008712 auto spy = createSpy();
8713 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8715
8716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8717 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8719 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8720 spy->assertNoEvents();
8721}
8722
8723/**
8724 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8725 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8726 * to the window.
8727 */
8728TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8729 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008730 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008731 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8732 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8733
8734 // Inject an event outside the spy window's touchable region.
8735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8736 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8738 window->consumeMotionDown();
8739 spy->assertNoEvents();
8740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8741 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8743 window->consumeMotionUp();
8744 spy->assertNoEvents();
8745
8746 // Inject an event inside the spy window's touchable region.
8747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8748 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8749 {5, 10}))
8750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8751 window->consumeMotionDown();
8752 spy->consumeMotionDown();
8753}
8754
8755/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008756 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008757 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008758 */
8759TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8760 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008761 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008762 auto spy = createSpy();
8763 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008764 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008765 spy->setFrame(Rect{0, 0, 20, 20});
8766 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8767
8768 // Inject an event outside the spy window's frame and touchable region.
8769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008770 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8771 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008772 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8773 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008774 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008775}
8776
8777/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008778 * Even when a spy window spans over multiple foreground windows, the spy should receive all
8779 * pointers that are down within its bounds.
8780 */
8781TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
8782 auto windowLeft = createForeground();
8783 windowLeft->setFrame({0, 0, 100, 200});
8784 auto windowRight = createForeground();
8785 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008786 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008787 spy->setFrame({0, 0, 200, 200});
8788 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
8789
8790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8791 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8792 {50, 50}))
8793 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8794 windowLeft->consumeMotionDown();
8795 spy->consumeMotionDown();
8796
8797 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008798 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008799 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008800 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8801 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008802 .build();
8803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8804 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8805 InputEventInjectionSync::WAIT_FOR_RESULT))
8806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8807 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00008808 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008809}
8810
8811/**
8812 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
8813 * the spy should receive the second pointer with ACTION_DOWN.
8814 */
8815TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
8816 auto window = createForeground();
8817 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008818 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008819 spyRight->setFrame({100, 0, 200, 200});
8820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
8821
8822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8823 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8824 {50, 50}))
8825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8826 window->consumeMotionDown();
8827 spyRight->assertNoEvents();
8828
8829 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008830 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008831 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008832 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8833 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008834 .build();
8835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8836 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8837 InputEventInjectionSync::WAIT_FOR_RESULT))
8838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008839 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008840 spyRight->consumeMotionDown();
8841}
8842
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008843/**
8844 * The spy window should not be able to affect whether or not touches are split. Only the foreground
8845 * windows should be allowed to control split touch.
8846 */
8847TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008848 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008849 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008850 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008851 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008852
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008853 auto window = createForeground();
8854 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008855
8856 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8857
8858 // First finger down, no window touched.
8859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8860 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8861 {100, 200}))
8862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8863 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8864 window->assertNoEvents();
8865
8866 // Second finger down on window, the window should receive touch down.
8867 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08008868 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008869 .displayId(ADISPLAY_ID_DEFAULT)
8870 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008871 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8872 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008873 .build();
8874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8875 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8876 InputEventInjectionSync::WAIT_FOR_RESULT))
8877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8878
8879 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00008880 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008881}
8882
8883/**
8884 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
8885 * do not receive key events.
8886 */
8887TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008888 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008889 spy->setFocusable(false);
8890
8891 auto window = createForeground();
8892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8893 setFocusedWindow(window);
8894 window->consumeFocusEvent(true);
8895
8896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
8897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8898 window->consumeKeyDown(ADISPLAY_ID_NONE);
8899
8900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
8901 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8902 window->consumeKeyUp(ADISPLAY_ID_NONE);
8903
8904 spy->assertNoEvents();
8905}
8906
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008907using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
8908
8909/**
8910 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
8911 * are currently sent to any other windows - including other spy windows - will also be cancelled.
8912 */
8913TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
8914 auto window = createForeground();
8915 auto spy1 = createSpy();
8916 auto spy2 = createSpy();
8917 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
8918
8919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8920 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8922 window->consumeMotionDown();
8923 spy1->consumeMotionDown();
8924 spy2->consumeMotionDown();
8925
8926 // Pilfer pointers from the second spy window.
8927 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
8928 spy2->assertNoEvents();
8929 spy1->consumeMotionCancel();
8930 window->consumeMotionCancel();
8931
8932 // The rest of the gesture should only be sent to the second spy window.
8933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8934 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8935 ADISPLAY_ID_DEFAULT))
8936 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8937 spy2->consumeMotionMove();
8938 spy1->assertNoEvents();
8939 window->assertNoEvents();
8940}
8941
8942/**
8943 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
8944 * in the middle of the gesture.
8945 */
8946TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
8947 auto window = createForeground();
8948 auto spy = createSpy();
8949 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8950
8951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8952 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8954 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8955 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8956
8957 window->releaseChannel();
8958
8959 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8960
8961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8962 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8964 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8965}
8966
8967/**
8968 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
8969 * the spy, but not to any other windows.
8970 */
8971TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
8972 auto spy = createSpy();
8973 auto window = createForeground();
8974
8975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8976
8977 // First finger down on the window and the spy.
8978 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8979 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8980 {100, 200}))
8981 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8982 spy->consumeMotionDown();
8983 window->consumeMotionDown();
8984
8985 // Spy window pilfers the pointers.
8986 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
8987 window->consumeMotionCancel();
8988
8989 // Second finger down on the window and spy, but the window should not receive the pointer down.
8990 const MotionEvent secondFingerDownEvent =
8991 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8992 .displayId(ADISPLAY_ID_DEFAULT)
8993 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008994 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8995 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00008996 .build();
8997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8998 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8999 InputEventInjectionSync::WAIT_FOR_RESULT))
9000 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9001
Harry Cutts33476232023-01-30 19:57:29 +00009002 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009003
9004 // Third finger goes down outside all windows, so injection should fail.
9005 const MotionEvent thirdFingerDownEvent =
9006 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9007 .displayId(ADISPLAY_ID_DEFAULT)
9008 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009009 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9010 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9011 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009012 .build();
9013 ASSERT_EQ(InputEventInjectionResult::FAILED,
9014 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9015 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009016 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009017
9018 spy->assertNoEvents();
9019 window->assertNoEvents();
9020}
9021
9022/**
9023 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9024 */
9025TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9026 auto spy = createSpy();
9027 spy->setFrame(Rect(0, 0, 100, 100));
9028 auto window = createForeground();
9029 window->setFrame(Rect(0, 0, 200, 200));
9030
9031 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9032
9033 // First finger down on the window only
9034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9035 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9036 {150, 150}))
9037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9038 window->consumeMotionDown();
9039
9040 // Second finger down on the spy and window
9041 const MotionEvent secondFingerDownEvent =
9042 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9043 .displayId(ADISPLAY_ID_DEFAULT)
9044 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009045 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9046 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009047 .build();
9048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9049 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9050 InputEventInjectionSync::WAIT_FOR_RESULT))
9051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9052 spy->consumeMotionDown();
9053 window->consumeMotionPointerDown(1);
9054
9055 // Third finger down on the spy and window
9056 const MotionEvent thirdFingerDownEvent =
9057 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9058 .displayId(ADISPLAY_ID_DEFAULT)
9059 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009060 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9061 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9062 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009063 .build();
9064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9065 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9066 InputEventInjectionSync::WAIT_FOR_RESULT))
9067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9068 spy->consumeMotionPointerDown(1);
9069 window->consumeMotionPointerDown(2);
9070
9071 // Spy window pilfers the pointers.
9072 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9073 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9074 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9075
9076 spy->assertNoEvents();
9077 window->assertNoEvents();
9078}
9079
9080/**
9081 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9082 * other windows should be canceled. If this results in the cancellation of all pointers for some
9083 * window, then that window should receive ACTION_CANCEL.
9084 */
9085TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9086 auto spy = createSpy();
9087 spy->setFrame(Rect(0, 0, 100, 100));
9088 auto window = createForeground();
9089 window->setFrame(Rect(0, 0, 200, 200));
9090
9091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9092
9093 // First finger down on both spy and window
9094 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9095 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9096 {10, 10}))
9097 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9098 window->consumeMotionDown();
9099 spy->consumeMotionDown();
9100
9101 // Second finger down on the spy and window
9102 const MotionEvent secondFingerDownEvent =
9103 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9104 .displayId(ADISPLAY_ID_DEFAULT)
9105 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009106 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9107 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009108 .build();
9109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9110 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9111 InputEventInjectionSync::WAIT_FOR_RESULT))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 spy->consumeMotionPointerDown(1);
9114 window->consumeMotionPointerDown(1);
9115
9116 // Spy window pilfers the pointers.
9117 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9118 window->consumeMotionCancel();
9119
9120 spy->assertNoEvents();
9121 window->assertNoEvents();
9122}
9123
9124/**
9125 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9126 * be sent to other windows
9127 */
9128TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9129 auto spy = createSpy();
9130 spy->setFrame(Rect(0, 0, 100, 100));
9131 auto window = createForeground();
9132 window->setFrame(Rect(0, 0, 200, 200));
9133
9134 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9135
9136 // First finger down on both window and spy
9137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9138 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9139 {10, 10}))
9140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9141 window->consumeMotionDown();
9142 spy->consumeMotionDown();
9143
9144 // Spy window pilfers the pointers.
9145 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9146 window->consumeMotionCancel();
9147
9148 // Second finger down on the window only
9149 const MotionEvent secondFingerDownEvent =
9150 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9151 .displayId(ADISPLAY_ID_DEFAULT)
9152 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009153 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9154 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009155 .build();
9156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9157 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9158 InputEventInjectionSync::WAIT_FOR_RESULT))
9159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9160 window->consumeMotionDown();
9161 window->assertNoEvents();
9162
9163 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9164 spy->consumeMotionMove();
9165 spy->assertNoEvents();
9166}
9167
Prabir Pradhand65552b2021-10-07 11:23:50 -07009168class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9169public:
9170 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9171 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9172 std::make_shared<FakeApplicationHandle>();
9173 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009174 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9175 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009176 overlay->setFocusable(false);
9177 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009178 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009179 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009180 overlay->setTrustedOverlay(true);
9181
9182 std::shared_ptr<FakeApplicationHandle> application =
9183 std::make_shared<FakeApplicationHandle>();
9184 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009185 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9186 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009187 window->setFocusable(true);
9188 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009189
9190 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9191 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9192 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009193 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009194 return {std::move(overlay), std::move(window)};
9195 }
9196
9197 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009198 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009199 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009200 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009201 }
9202
9203 void sendStylusEvent(int32_t action) {
9204 NotifyMotionArgs motionArgs =
9205 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9206 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009207 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009208 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009209 }
9210};
9211
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009212using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9213
9214TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9215 ScopedSilentDeath _silentDeath;
9216
Prabir Pradhand65552b2021-10-07 11:23:50 -07009217 auto [overlay, window] = setupStylusOverlayScenario();
9218 overlay->setTrustedOverlay(false);
9219 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9220 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9221 ".* not a trusted overlay");
9222}
9223
9224TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9225 auto [overlay, window] = setupStylusOverlayScenario();
9226 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9227
9228 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9229 overlay->consumeMotionDown();
9230 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9231 overlay->consumeMotionUp();
9232
9233 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9234 window->consumeMotionDown();
9235 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9236 window->consumeMotionUp();
9237
9238 overlay->assertNoEvents();
9239 window->assertNoEvents();
9240}
9241
9242TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9243 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009244 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009245 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9246
9247 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9248 overlay->consumeMotionDown();
9249 window->consumeMotionDown();
9250 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9251 overlay->consumeMotionUp();
9252 window->consumeMotionUp();
9253
9254 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9255 window->consumeMotionDown();
9256 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9257 window->consumeMotionUp();
9258
9259 overlay->assertNoEvents();
9260 window->assertNoEvents();
9261}
9262
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009263/**
9264 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9265 * The scenario is as follows:
9266 * - The stylus interceptor overlay is configured as a spy window.
9267 * - The stylus interceptor spy receives the start of a new stylus gesture.
9268 * - It pilfers pointers and then configures itself to no longer be a spy.
9269 * - The stylus interceptor continues to receive the rest of the gesture.
9270 */
9271TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9272 auto [overlay, window] = setupStylusOverlayScenario();
9273 overlay->setSpy(true);
9274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9275
9276 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9277 overlay->consumeMotionDown();
9278 window->consumeMotionDown();
9279
9280 // The interceptor pilfers the pointers.
9281 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9282 window->consumeMotionCancel();
9283
9284 // The interceptor configures itself so that it is no longer a spy.
9285 overlay->setSpy(false);
9286 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9287
9288 // It continues to receive the rest of the stylus gesture.
9289 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9290 overlay->consumeMotionMove();
9291 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9292 overlay->consumeMotionUp();
9293
9294 window->assertNoEvents();
9295}
9296
Prabir Pradhan5735a322022-04-11 17:23:34 +00009297struct User {
9298 int32_t mPid;
9299 int32_t mUid;
9300 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9301 std::unique_ptr<InputDispatcher>& mDispatcher;
9302
9303 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9304 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9305
9306 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9307 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9308 ADISPLAY_ID_DEFAULT, {100, 200},
9309 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9310 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9311 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9312 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9313 }
9314
9315 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009316 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009317 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009318 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009319 mPolicyFlags);
9320 }
9321
9322 sp<FakeWindowHandle> createWindow() const {
9323 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9324 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009325 sp<FakeWindowHandle> window =
9326 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9327 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009328 window->setOwnerInfo(mPid, mUid);
9329 return window;
9330 }
9331};
9332
9333using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9334
9335TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9336 auto owner = User(mDispatcher, 10, 11);
9337 auto window = owner.createWindow();
9338 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9339
9340 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9341 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9342 window->consumeMotionDown();
9343
9344 setFocusedWindow(window);
9345 window->consumeFocusEvent(true);
9346
9347 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9348 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9349 window->consumeKeyDown(ADISPLAY_ID_NONE);
9350}
9351
9352TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9353 auto owner = User(mDispatcher, 10, 11);
9354 auto window = owner.createWindow();
9355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9356
9357 auto rando = User(mDispatcher, 20, 21);
9358 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9359 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9360
9361 setFocusedWindow(window);
9362 window->consumeFocusEvent(true);
9363
9364 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9365 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9366 window->assertNoEvents();
9367}
9368
9369TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9370 auto owner = User(mDispatcher, 10, 11);
9371 auto window = owner.createWindow();
9372 auto spy = owner.createWindow();
9373 spy->setSpy(true);
9374 spy->setTrustedOverlay(true);
9375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9376
9377 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9378 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9379 spy->consumeMotionDown();
9380 window->consumeMotionDown();
9381}
9382
9383TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9384 auto owner = User(mDispatcher, 10, 11);
9385 auto window = owner.createWindow();
9386
9387 auto rando = User(mDispatcher, 20, 21);
9388 auto randosSpy = rando.createWindow();
9389 randosSpy->setSpy(true);
9390 randosSpy->setTrustedOverlay(true);
9391 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9392
9393 // The event is targeted at owner's window, so injection should succeed, but the spy should
9394 // not receive the event.
9395 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9396 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9397 randosSpy->assertNoEvents();
9398 window->consumeMotionDown();
9399}
9400
9401TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9402 auto owner = User(mDispatcher, 10, 11);
9403 auto window = owner.createWindow();
9404
9405 auto rando = User(mDispatcher, 20, 21);
9406 auto randosSpy = rando.createWindow();
9407 randosSpy->setSpy(true);
9408 randosSpy->setTrustedOverlay(true);
9409 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9410
9411 // A user that has injection permission can inject into any window.
9412 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9413 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9414 ADISPLAY_ID_DEFAULT));
9415 randosSpy->consumeMotionDown();
9416 window->consumeMotionDown();
9417
9418 setFocusedWindow(randosSpy);
9419 randosSpy->consumeFocusEvent(true);
9420
9421 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9422 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9423 window->assertNoEvents();
9424}
9425
9426TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9427 auto owner = User(mDispatcher, 10, 11);
9428 auto window = owner.createWindow();
9429
9430 auto rando = User(mDispatcher, 20, 21);
9431 auto randosWindow = rando.createWindow();
9432 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9433 randosWindow->setWatchOutsideTouch(true);
9434 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9435
9436 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9437 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9438 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9439 window->consumeMotionDown();
9440 randosWindow->consumeMotionOutside();
9441}
9442
Garfield Tane84e6f92019-08-29 17:28:41 -07009443} // namespace android::inputdispatcher