blob: 8e9d990b28dcbfe1179e4569cb1c2174354a30d8 [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;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070065static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080067static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080068static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080069/**
70 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
71 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
72 * index 0) is the new pointer going down. The same pointer could have been placed at a different
73 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
74 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
75 * pointer id=0 leaves but the pointer id=1 remains.
76 */
77static constexpr int32_t POINTER_0_DOWN =
78 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080079static constexpr int32_t POINTER_1_DOWN =
80 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000081static constexpr int32_t POINTER_2_DOWN =
82 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000083static constexpr int32_t POINTER_3_DOWN =
84 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000085static constexpr int32_t POINTER_0_UP =
86 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080087static constexpr int32_t POINTER_1_UP =
88 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000089static constexpr int32_t POINTER_2_UP =
90 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080091
Antonio Kantek15beb512022-06-13 22:35:41 +000092// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000093static constexpr int32_t WINDOW_PID = 999;
94static constexpr int32_t WINDOW_UID = 1001;
95
Antonio Kantek15beb512022-06-13 22:35:41 +000096// The default pid and uid for the windows created on the secondary display by the test.
97static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
98static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
99
Prabir Pradhan5735a322022-04-11 17:23:34 +0000100// The default policy flags to use for event injection by tests.
101static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800102
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000103// An arbitrary pid of the gesture monitor window
104static constexpr int32_t MONITOR_PID = 2001;
105
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800106static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
107
Arthur Hungc539dbb2022-12-08 07:45:36 +0000108static constexpr int expectedWallpaperFlags =
109 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
110
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800111using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
112
chaviwd1c23182019-12-20 18:44:56 -0800113struct PointF {
114 float x;
115 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800116 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800117};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800118
Gang Wang342c9272020-01-13 13:15:04 -0500119/**
120 * Return a DOWN key event with KEYCODE_A.
121 */
122static KeyEvent getTestKeyEvent() {
123 KeyEvent event;
124
Garfield Tanfbe732e2020-01-24 11:26:14 -0800125 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
126 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
127 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500128 return event;
129}
130
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000131static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
132 ASSERT_EQ(expectedAction, receivedAction)
133 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
134 << MotionEvent::actionToString(receivedAction);
135}
136
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800137MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
138 bool matches = action == arg.getAction();
139 if (!matches) {
140 *result_listener << "expected action " << MotionEvent::actionToString(action)
141 << ", but got " << MotionEvent::actionToString(arg.getAction());
142 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800143 if (action == AMOTION_EVENT_ACTION_DOWN) {
144 if (!matches) {
145 *result_listener << "; ";
146 }
147 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
148 matches &= arg.getDownTime() == arg.getEventTime();
149 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800150 if (action == AMOTION_EVENT_ACTION_CANCEL) {
151 if (!matches) {
152 *result_listener << "; ";
153 }
154 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
155 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
156 }
157 return matches;
158}
159
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800160MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
161 return arg.getDownTime() == downTime;
162}
163
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800164MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
165 return arg.getDisplayId() == displayId;
166}
167
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800168MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
169 return arg.getDeviceId() == deviceId;
170}
171
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800172MATCHER_P(WithSource, source, "InputEvent with specified source") {
173 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
174 << inputEventSourceToString(arg.getSource());
175 return arg.getSource() == source;
176}
177
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800178MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
179 return arg.getFlags() == flags;
180}
181
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800182MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
183 if (arg.getPointerCount() != 1) {
184 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
185 return false;
186 }
Harry Cutts33476232023-01-30 19:57:29 +0000187 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800188}
189
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800190MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
191 return arg.getPointerCount() == pointerCount;
192}
193
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800194MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
195 // Build a map for the received pointers, by pointer id
196 std::map<int32_t /*pointerId*/, PointF> actualPointers;
197 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
198 const int32_t pointerId = arg.getPointerId(pointerIndex);
199 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
200 }
201 return pointers == actualPointers;
202}
203
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204// --- FakeInputDispatcherPolicy ---
205
206class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800207 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
208
Michael Wrightd02c5b62014-02-10 15:10:22 -0800209public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000210 FakeInputDispatcherPolicy() = default;
211 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800212
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800213 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700214 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700215 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700216 EXPECT_EQ(event.getDisplayId(), args.displayId);
217
218 const auto& keyEvent = static_cast<const KeyEvent&>(event);
219 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
220 EXPECT_EQ(keyEvent.getAction(), args.action);
221 });
Jackal Guof9696682018-10-05 12:23:23 +0800222 }
223
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700224 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
225 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700226 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700227 EXPECT_EQ(event.getDisplayId(), args.displayId);
228
229 const auto& motionEvent = static_cast<const MotionEvent&>(event);
230 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
231 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000232 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
233 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
234 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
235 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700236 });
Jackal Guof9696682018-10-05 12:23:23 +0800237 }
238
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700239 void assertFilterInputEventWasNotCalled() {
240 std::scoped_lock lock(mLock);
241 ASSERT_EQ(nullptr, mFilteredEvent);
242 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800243
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800244 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700245 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800246 ASSERT_TRUE(mConfigurationChangedTime)
247 << "Timed out waiting for configuration changed call";
248 ASSERT_EQ(*mConfigurationChangedTime, when);
249 mConfigurationChangedTime = std::nullopt;
250 }
251
252 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700253 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800254 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800255 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800256 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
257 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
258 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
259 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
260 mLastNotifySwitch = std::nullopt;
261 }
262
chaviwfd6d3512019-03-25 13:23:49 -0700263 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700264 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800265 ASSERT_EQ(touchedToken, mOnPointerDownToken);
266 mOnPointerDownToken.clear();
267 }
268
269 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700270 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800271 ASSERT_TRUE(mOnPointerDownToken == nullptr)
272 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700273 }
274
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700275 // This function must be called soon after the expected ANR timer starts,
276 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500277 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700278 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500279 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800280 std::unique_lock lock(mLock);
281 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800283 ASSERT_NO_FATAL_FAILURE(
284 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500285 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700286 }
287
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000288 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800289 const sp<WindowInfoHandle>& window) {
290 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
291 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
292 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500293 }
294
Prabir Pradhanedd96402022-02-15 01:46:16 -0800295 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
296 const sp<IBinder>& expectedToken,
297 int32_t expectedPid) {
298 std::unique_lock lock(mLock);
299 android::base::ScopedLockAssertion assumeLocked(mLock);
300 AnrResult result;
301 ASSERT_NO_FATAL_FAILURE(result =
302 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
303 const auto& [token, pid] = result;
304 ASSERT_EQ(expectedToken, token);
305 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500306 }
307
Prabir Pradhanedd96402022-02-15 01:46:16 -0800308 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000309 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 std::unique_lock lock(mLock);
311 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800312 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
313 const auto& [token, _] = result;
314 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000315 }
316
Prabir Pradhanedd96402022-02-15 01:46:16 -0800317 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
318 int32_t expectedPid) {
319 std::unique_lock lock(mLock);
320 android::base::ScopedLockAssertion assumeLocked(mLock);
321 AnrResult result;
322 ASSERT_NO_FATAL_FAILURE(
323 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
324 const auto& [token, pid] = result;
325 ASSERT_EQ(expectedToken, token);
326 ASSERT_EQ(expectedPid, pid);
327 }
328
329 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000330 sp<IBinder> getResponsiveWindowToken() {
331 std::unique_lock lock(mLock);
332 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800333 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
334 const auto& [token, _] = result;
335 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700336 }
337
338 void assertNotifyAnrWasNotCalled() {
339 std::scoped_lock lock(mLock);
340 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800341 ASSERT_TRUE(mAnrWindows.empty());
342 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500343 << "ANR was not called, but please also consume the 'connection is responsive' "
344 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700345 }
346
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000347 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800348 std::unique_lock lock(mLock);
349 base::ScopedLockAssertion assumeLocked(mLock);
350
351 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
352 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000353 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800354 enabled;
355 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000356 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
357 << ") to be called.";
358 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800359 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000360 auto request = *mPointerCaptureRequest;
361 mPointerCaptureRequest.reset();
362 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 }
364
365 void assertSetPointerCaptureNotCalled() {
366 std::unique_lock lock(mLock);
367 base::ScopedLockAssertion assumeLocked(mLock);
368
369 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000370 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800371 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000372 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000374 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800375 }
376
arthurhungf452d0b2021-01-06 00:19:52 +0800377 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
378 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800379 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800380 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800381 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800382 }
383
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800384 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
385 std::unique_lock lock(mLock);
386 base::ScopedLockAssertion assumeLocked(mLock);
387 std::optional<sp<IBinder>> receivedToken =
388 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
389 mNotifyInputChannelBroken);
390 ASSERT_TRUE(receivedToken.has_value());
391 ASSERT_EQ(token, *receivedToken);
392 }
393
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800394 /**
395 * Set policy timeout. A value of zero means next key will not be intercepted.
396 */
397 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
398 mInterceptKeyTimeout = timeout;
399 }
400
Josep del Riob3981622023-04-18 15:49:45 +0000401 void assertUserActivityPoked() {
402 std::scoped_lock lock(mLock);
403 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
404 }
405
406 void assertUserActivityNotPoked() {
407 std::scoped_lock lock(mLock);
408 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
409 }
410
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700412 std::mutex mLock;
413 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
414 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
415 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
416 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800417
Prabir Pradhan99987712020-11-10 18:43:05 -0800418 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000419
420 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800421
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700422 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700423 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800424 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
425 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700426 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800427 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
428 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700429
arthurhungf452d0b2021-01-06 00:19:52 +0800430 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800431 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000432 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800433
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800434 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
435
Prabir Pradhanedd96402022-02-15 01:46:16 -0800436 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
437 // for a specific container to become non-empty. When the container is non-empty, return the
438 // first entry from the container and erase it.
439 template <class T>
440 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
441 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
442 // If there is an ANR, Dispatcher won't be idle because there are still events
443 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
444 // before checking if ANR was called.
445 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
446 // to provide it some time to act. 100ms seems reasonable.
447 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
448 const std::chrono::time_point start = std::chrono::steady_clock::now();
449 std::optional<T> token =
450 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
451 if (!token.has_value()) {
452 ADD_FAILURE() << "Did not receive the ANR callback";
453 return {};
454 }
455
456 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
457 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
458 // the dispatcher started counting before this function was called
459 if (std::chrono::abs(timeout - waited) > 100ms) {
460 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
461 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
462 << "ms, but waited "
463 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
464 << "ms instead";
465 }
466 return *token;
467 }
468
469 template <class T>
470 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
471 std::queue<T>& storage,
472 std::unique_lock<std::mutex>& lock,
473 std::condition_variable& condition)
474 REQUIRES(mLock) {
475 condition.wait_for(lock, timeout,
476 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
477 if (storage.empty()) {
478 ADD_FAILURE() << "Did not receive the expected callback";
479 return std::nullopt;
480 }
481 T item = storage.front();
482 storage.pop();
483 return std::make_optional(item);
484 }
485
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600486 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700487 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800488 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800489 }
490
Prabir Pradhanedd96402022-02-15 01:46:16 -0800491 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
492 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700493 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800494 ASSERT_TRUE(pid.has_value());
495 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700496 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500497 }
498
Prabir Pradhanedd96402022-02-15 01:46:16 -0800499 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
500 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500501 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800502 ASSERT_TRUE(pid.has_value());
503 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500504 mNotifyAnr.notify_all();
505 }
506
507 void notifyNoFocusedWindowAnr(
508 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
509 std::scoped_lock lock(mLock);
510 mAnrApplications.push(applicationHandle);
511 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800512 }
513
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800514 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
515 std::scoped_lock lock(mLock);
516 mBrokenInputChannels.push(connectionToken);
517 mNotifyInputChannelBroken.notify_all();
518 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800519
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600520 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700521
Chris Yef59a2f42020-10-16 12:55:26 -0700522 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
523 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
524 const std::vector<float>& values) override {}
525
526 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
527 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000528
Chris Yefb552902021-02-03 17:18:37 -0800529 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
530
Prabir Pradhana41d2442023-04-20 21:30:40 +0000531 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700532 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000533 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700534 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000535 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
536 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800537 break;
538 }
539
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700540 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000541 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
542 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800543 break;
544 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700545 default: {
546 ADD_FAILURE() << "Should only filter keys or motions";
547 break;
548 }
Jackal Guof9696682018-10-05 12:23:23 +0800549 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550 return true;
551 }
552
Prabir Pradhana41d2442023-04-20 21:30:40 +0000553 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
554 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800555 // Clear intercept state when we handled the event.
556 mInterceptKeyTimeout = 0ms;
557 }
558 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800559
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600560 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800561
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800563 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
564 // Clear intercept state so we could dispatch the event in next wake.
565 mInterceptKeyTimeout = 0ms;
566 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800567 }
568
Prabir Pradhana41d2442023-04-20 21:30:40 +0000569 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
570 uint32_t) override {
571 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800572 }
573
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600574 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
575 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700576 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800577 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
578 * essentially a passthrough for notifySwitch.
579 */
Harry Cutts33476232023-01-30 19:57:29 +0000580 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581 }
582
Josep del Riob3981622023-04-18 15:49:45 +0000583 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
584 std::scoped_lock lock(mLock);
585 mPokedUserActivity = true;
586 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600588 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700589 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700590 mOnPointerDownToken = newToken;
591 }
592
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000593 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800594 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000595 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800596 mPointerCaptureChangedCondition.notify_all();
597 }
598
arthurhungf452d0b2021-01-06 00:19:52 +0800599 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
600 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800601 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800602 mDropTargetWindowToken = token;
603 }
604
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700605 void assertFilterInputEventWasCalledInternal(
606 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700607 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800608 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700609 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800610 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800611 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800612};
613
Michael Wrightd02c5b62014-02-10 15:10:22 -0800614// --- InputDispatcherTest ---
615
616class InputDispatcherTest : public testing::Test {
617protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000618 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700619 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800620
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000621 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000622 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
623 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800624 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000625 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700626 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800627 }
628
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000629 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700630 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000631 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700632 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800633 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700634
635 /**
636 * Used for debugging when writing the test
637 */
638 void dumpDispatcherState() {
639 std::string dump;
640 mDispatcher->dump(dump);
641 std::stringstream ss(dump);
642 std::string to;
643
644 while (std::getline(ss, to, '\n')) {
645 ALOGE("%s", to.c_str());
646 }
647 }
Vishnu Nair958da932020-08-21 17:12:37 -0700648
Chavi Weingarten847e8512023-03-29 00:26:09 +0000649 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700650 FocusRequest request;
651 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000652 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700653 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
654 request.displayId = window->getInfo()->displayId;
655 mDispatcher->setFocusedWindow(request);
656 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800657};
658
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
660 KeyEvent event;
661
662 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800663 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
664 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600665 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
666 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800667 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000668 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000669 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800670 << "Should reject key events with undefined action.";
671
672 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800673 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
674 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600675 ARBITRARY_TIME, 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 ACTION_MULTIPLE.";
680}
681
682TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
683 MotionEvent event;
684 PointerProperties pointerProperties[MAX_POINTERS + 1];
685 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800686 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800687 pointerProperties[i].clear();
688 pointerProperties[i].id = i;
689 pointerCoords[i].clear();
690 }
691
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800692 // Some constants commonly used below
693 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
694 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
695 constexpr int32_t metaState = AMETA_NONE;
696 constexpr MotionClassification classification = MotionClassification::NONE;
697
chaviw9eaa22c2020-07-01 16:21:27 -0700698 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800700 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700701 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
702 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700703 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
704 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700705 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800706 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000707 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000708 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800709 << "Should reject motion events with undefined action.";
710
711 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800712 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800713 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
714 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
715 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
716 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500717 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800718 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000719 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000720 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800721 << "Should reject motion events with pointer down index too large.";
722
Garfield Tanfbe732e2020-01-24 11:26:14 -0800723 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700724 AMOTION_EVENT_ACTION_POINTER_DOWN |
725 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700726 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
727 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700728 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500729 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800730 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000731 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000732 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800733 << "Should reject motion events with pointer down index too small.";
734
735 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800736 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800737 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
738 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
739 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
740 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500741 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800742 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000743 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000744 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800745 << "Should reject motion events with pointer up index too large.";
746
Garfield Tanfbe732e2020-01-24 11:26:14 -0800747 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700748 AMOTION_EVENT_ACTION_POINTER_UP |
749 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700750 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
751 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700752 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500753 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800754 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000755 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000756 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800757 << "Should reject motion events with pointer up index too small.";
758
759 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800760 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
761 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700762 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700763 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
764 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700765 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800766 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000767 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000768 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800769 << "Should reject motion events with 0 pointers.";
770
Garfield Tanfbe732e2020-01-24 11:26:14 -0800771 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
772 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700773 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700774 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
775 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700776 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800777 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000778 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000779 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800780 << "Should reject motion events with more than MAX_POINTERS pointers.";
781
782 // Rejects motion events with invalid pointer ids.
783 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800784 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
785 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700786 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700787 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
788 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700789 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800790 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000791 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000792 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800793 << "Should reject motion events with pointer ids less than 0.";
794
795 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800796 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
797 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700798 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700799 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
800 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700801 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800802 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000803 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000804 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800805 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
806
807 // Rejects motion events with duplicate pointer ids.
808 pointerProperties[0].id = 1;
809 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800810 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
811 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700812 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700813 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
814 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700815 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800816 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000817 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000818 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800819 << "Should reject motion events with duplicate pointer ids.";
820}
821
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800822/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
823
824TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
825 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000826 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800827 ASSERT_TRUE(mDispatcher->waitForIdle());
828
829 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
830}
831
832TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000833 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
834 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000835 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800836
837 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
838 args.policyFlags |= POLICY_FLAG_TRUSTED;
839 mFakePolicy->assertNotifySwitchWasCalled(args);
840}
841
Arthur Hungb92218b2018-08-14 12:00:21 +0800842// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700843static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700844// Default input dispatching timeout if there is no focused application or paused window
845// from which to determine an appropriate dispatching timeout.
846static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
847 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
848 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800849
850class FakeApplicationHandle : public InputApplicationHandle {
851public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700852 FakeApplicationHandle() {
853 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700854 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500855 mInfo.dispatchingTimeoutMillis =
856 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700857 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800858 virtual ~FakeApplicationHandle() {}
859
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000860 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700861
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500862 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
863 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700864 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800865};
866
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800867class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800868public:
Garfield Tan15601662020-09-22 15:32:38 -0700869 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800870 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700871 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800872 }
873
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800874 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700875 InputEvent* event;
876 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
877 if (!consumeSeq) {
878 return nullptr;
879 }
880 finishEvent(*consumeSeq);
881 return event;
882 }
883
884 /**
885 * Receive an event without acknowledging it.
886 * Return the sequence number that could later be used to send finished signal.
887 */
888 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800889 uint32_t consumeSeq;
890 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800891
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800892 std::chrono::time_point start = std::chrono::steady_clock::now();
893 status_t status = WOULD_BLOCK;
894 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000895 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896 &event);
897 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
898 if (elapsed > 100ms) {
899 break;
900 }
901 }
902
903 if (status == WOULD_BLOCK) {
904 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700905 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800906 }
907
908 if (status != OK) {
909 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700910 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800911 }
912 if (event == nullptr) {
913 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700914 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800915 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 if (outEvent != nullptr) {
917 *outEvent = event;
918 }
919 return consumeSeq;
920 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700922 /**
923 * To be used together with "receiveEvent" to complete the consumption of an event.
924 */
925 void finishEvent(uint32_t consumeSeq) {
926 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
927 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 }
929
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000930 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
931 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
932 ASSERT_EQ(OK, status);
933 }
934
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700935 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000936 std::optional<int32_t> expectedDisplayId,
937 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800938 InputEvent* event = consume();
939
940 ASSERT_NE(nullptr, event) << mName.c_str()
941 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800942 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700943 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
944 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800945
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000946 if (expectedDisplayId.has_value()) {
947 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
948 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800949
Tiger Huang8664f8c2018-10-11 19:14:35 +0800950 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700951 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800952 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
953 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000954 if (expectedFlags.has_value()) {
955 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
956 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800957 break;
958 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700959 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800960 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000961 assertMotionAction(expectedAction, motionEvent.getAction());
962
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000963 if (expectedFlags.has_value()) {
964 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
965 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800966 break;
967 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700968 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100969 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
970 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700971 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800972 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
973 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700974 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000975 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
976 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700977 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800978 FAIL() << "Use 'consumeDragEvent' for DRAG events";
979 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800980 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800981 }
982
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800983 MotionEvent* consumeMotion() {
984 InputEvent* event = consume();
985
986 if (event == nullptr) {
987 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
988 return nullptr;
989 }
990
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700991 if (event->getType() != InputEventType::MOTION) {
992 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800993 return nullptr;
994 }
995 return static_cast<MotionEvent*>(event);
996 }
997
998 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
999 MotionEvent* motionEvent = consumeMotion();
1000 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1001 ASSERT_THAT(*motionEvent, matcher);
1002 }
1003
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001004 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1005 InputEvent* event = consume();
1006 ASSERT_NE(nullptr, event) << mName.c_str()
1007 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001008 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1009 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001010
1011 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1012 << mName.c_str() << ": event displayId should always be NONE.";
1013
1014 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1015 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001016 }
1017
Prabir Pradhan99987712020-11-10 18:43:05 -08001018 void consumeCaptureEvent(bool hasCapture) {
1019 const InputEvent* event = consume();
1020 ASSERT_NE(nullptr, event) << mName.c_str()
1021 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001022 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1023 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001024
1025 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1026 << mName.c_str() << ": event displayId should always be NONE.";
1027
1028 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1029 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1030 }
1031
arthurhungb89ccb02020-12-30 16:19:01 +08001032 void consumeDragEvent(bool isExiting, float x, float y) {
1033 const InputEvent* event = consume();
1034 ASSERT_NE(nullptr, event) << mName.c_str()
1035 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001036 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001037
1038 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1039 << mName.c_str() << ": event displayId should always be NONE.";
1040
1041 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1042 EXPECT_EQ(isExiting, dragEvent.isExiting());
1043 EXPECT_EQ(x, dragEvent.getX());
1044 EXPECT_EQ(y, dragEvent.getY());
1045 }
1046
Antonio Kantekf16f2832021-09-28 04:39:20 +00001047 void consumeTouchModeEvent(bool inTouchMode) {
1048 const InputEvent* event = consume();
1049 ASSERT_NE(nullptr, event) << mName.c_str()
1050 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001051 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1052 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001053
1054 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1055 << mName.c_str() << ": event displayId should always be NONE.";
1056 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1057 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1058 }
1059
chaviwd1c23182019-12-20 18:44:56 -08001060 void assertNoEvents() {
1061 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001062 if (event == nullptr) {
1063 return;
1064 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001066 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1067 ADD_FAILURE() << "Received key event "
1068 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001069 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001070 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1071 ADD_FAILURE() << "Received motion event "
1072 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001074 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1075 ADD_FAILURE() << "Received focus event, hasFocus = "
1076 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001077 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001078 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1079 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1080 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001081 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001082 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1083 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1084 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001085 }
1086 FAIL() << mName.c_str()
1087 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001088 }
1089
1090 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1091
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001092 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1093
chaviwd1c23182019-12-20 18:44:56 -08001094protected:
1095 std::unique_ptr<InputConsumer> mConsumer;
1096 PreallocatedInputEventFactory mEventFactory;
1097
1098 std::string mName;
1099};
1100
chaviw3277faf2021-05-19 16:45:23 -05001101class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001102public:
1103 static const int32_t WIDTH = 600;
1104 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001105
Chris Yea209fde2020-07-22 13:54:51 -07001106 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001107 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001108 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001109 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001110 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001111 base::Result<std::unique_ptr<InputChannel>> channel =
1112 dispatcher->createInputChannel(name);
1113 token = (*channel)->getConnectionToken();
1114 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001115 }
1116
1117 inputApplicationHandle->updateInfo();
1118 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1119
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001120 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001121 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001122 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001123 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001124 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001125 mInfo.frameLeft = 0;
1126 mInfo.frameTop = 0;
1127 mInfo.frameRight = WIDTH;
1128 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001129 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001130 mInfo.globalScaleFactor = 1.0;
1131 mInfo.touchableRegion.clear();
1132 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001133 mInfo.ownerPid = WINDOW_PID;
1134 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001135 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001136 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001137 }
1138
Arthur Hungabbb9d82021-09-01 14:52:30 +00001139 sp<FakeWindowHandle> clone(
1140 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001141 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001142 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001143 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1144 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001145 return handle;
1146 }
1147
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001148 void setTouchable(bool touchable) {
1149 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1150 }
chaviwd1c23182019-12-20 18:44:56 -08001151
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001152 void setFocusable(bool focusable) {
1153 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1154 }
1155
1156 void setVisible(bool visible) {
1157 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1158 }
Vishnu Nair958da932020-08-21 17:12:37 -07001159
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001160 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001161 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001162 }
1163
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001164 void setPaused(bool paused) {
1165 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1166 }
1167
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001168 void setPreventSplitting(bool preventSplitting) {
1169 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 }
1171
1172 void setSlippery(bool slippery) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1174 }
1175
1176 void setWatchOutsideTouch(bool watchOutside) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1178 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001179
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001180 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1181
1182 void setInterceptsStylus(bool interceptsStylus) {
1183 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1184 }
1185
1186 void setDropInput(bool dropInput) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1188 }
1189
1190 void setDropInputIfObscured(bool dropInputIfObscured) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1192 }
1193
1194 void setNoInputChannel(bool noInputChannel) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1196 }
1197
Josep del Riob3981622023-04-18 15:49:45 +00001198 void setDisableUserActivity(bool disableUserActivity) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1200 }
1201
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001202 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1203
chaviw3277faf2021-05-19 16:45:23 -05001204 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001205
Bernardo Rufino7393d172021-02-26 13:56:11 +00001206 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1207
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001208 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001209 mInfo.frameLeft = frame.left;
1210 mInfo.frameTop = frame.top;
1211 mInfo.frameRight = frame.right;
1212 mInfo.frameBottom = frame.bottom;
1213 mInfo.touchableRegion.clear();
1214 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001215
1216 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1217 ui::Transform translate;
1218 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1219 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001220 }
1221
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001222 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1223
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001224 void setIsWallpaper(bool isWallpaper) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1226 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001227
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001228 void setDupTouchToWallpaper(bool hasWallpaper) {
1229 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1230 }
chaviwd1c23182019-12-20 18:44:56 -08001231
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001232 void setTrustedOverlay(bool trustedOverlay) {
1233 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1234 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001235
chaviw9eaa22c2020-07-01 16:21:27 -07001236 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1237 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1238 }
1239
1240 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001241
yunho.shinf4a80b82020-11-16 21:13:57 +09001242 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1243
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001244 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001245 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001246 }
1247
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001248 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001249 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001250 }
1251
Svet Ganov5d3bc372020-01-26 23:11:07 -08001252 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001253 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001254 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1255 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001256 }
1257
1258 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001259 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001260 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1261 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001262 }
1263
1264 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001265 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001266 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1267 }
1268
1269 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1270 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001271 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001272 expectedFlags);
1273 }
1274
Svet Ganov5d3bc372020-01-26 23:11:07 -08001275 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001276 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1277 int32_t expectedFlags = 0) {
1278 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1279 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001280 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001281 }
1282
1283 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001284 int32_t expectedFlags = 0) {
1285 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1286 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001287 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001288 }
1289
1290 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001291 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001292 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001293 expectedFlags);
1294 }
1295
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001296 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1297 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001298 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001299 expectedFlags);
1300 }
1301
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001302 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1303 int32_t expectedFlags = 0) {
1304 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001305 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001306 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001307 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1308 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1309 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1310 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1311 }
1312
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001313 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1314 ASSERT_NE(mInputReceiver, nullptr)
1315 << "Cannot consume events from a window with no receiver";
1316 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1317 }
1318
Prabir Pradhan99987712020-11-10 18:43:05 -08001319 void consumeCaptureEvent(bool hasCapture) {
1320 ASSERT_NE(mInputReceiver, nullptr)
1321 << "Cannot consume events from a window with no receiver";
1322 mInputReceiver->consumeCaptureEvent(hasCapture);
1323 }
1324
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001325 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1326 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001327 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001328 ASSERT_THAT(*motionEvent, matcher);
1329 }
1330
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001332 std::optional<int32_t> expectedDisplayId,
1333 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001334 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1335 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1336 expectedFlags);
1337 }
1338
arthurhungb89ccb02020-12-30 16:19:01 +08001339 void consumeDragEvent(bool isExiting, float x, float y) {
1340 mInputReceiver->consumeDragEvent(isExiting, x, y);
1341 }
1342
Antonio Kantekf16f2832021-09-28 04:39:20 +00001343 void consumeTouchModeEvent(bool inTouchMode) {
1344 ASSERT_NE(mInputReceiver, nullptr)
1345 << "Cannot consume events from a window with no receiver";
1346 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1347 }
1348
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001349 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001350 if (mInputReceiver == nullptr) {
1351 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1352 return std::nullopt;
1353 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001354 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001355 }
1356
1357 void finishEvent(uint32_t sequenceNum) {
1358 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1359 mInputReceiver->finishEvent(sequenceNum);
1360 }
1361
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001362 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1363 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1364 mInputReceiver->sendTimeline(inputEventId, timeline);
1365 }
1366
chaviwaf87b3e2019-10-01 16:59:28 -07001367 InputEvent* consume() {
1368 if (mInputReceiver == nullptr) {
1369 return nullptr;
1370 }
1371 return mInputReceiver->consume();
1372 }
1373
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001374 MotionEvent* consumeMotion() {
1375 InputEvent* event = consume();
1376 if (event == nullptr) {
1377 ADD_FAILURE() << "Consume failed : no event";
1378 return nullptr;
1379 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001380 if (event->getType() != InputEventType::MOTION) {
1381 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001382 return nullptr;
1383 }
1384 return static_cast<MotionEvent*>(event);
1385 }
1386
Arthur Hungb92218b2018-08-14 12:00:21 +08001387 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001388 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001389 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001390 return; // Can't receive events if the window does not have input channel
1391 }
1392 ASSERT_NE(nullptr, mInputReceiver)
1393 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001394 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001395 }
1396
chaviwaf87b3e2019-10-01 16:59:28 -07001397 sp<IBinder> getToken() { return mInfo.token; }
1398
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001399 const std::string& getName() { return mName; }
1400
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001401 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1402 mInfo.ownerPid = ownerPid;
1403 mInfo.ownerUid = ownerUid;
1404 }
1405
Prabir Pradhanedd96402022-02-15 01:46:16 -08001406 int32_t getPid() const { return mInfo.ownerPid; }
1407
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001408 void destroyReceiver() { mInputReceiver = nullptr; }
1409
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001410 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1411
chaviwd1c23182019-12-20 18:44:56 -08001412private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001413 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001414 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001415 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001416};
1417
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001418std::atomic<int32_t> FakeWindowHandle::sId{1};
1419
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001420static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001421 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001422 int32_t displayId = ADISPLAY_ID_NONE,
1423 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001424 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001425 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1426 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001427 KeyEvent event;
1428 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1429
1430 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001431 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001432 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1433 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001434
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001435 if (!allowKeyRepeat) {
1436 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1437 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001438 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001439 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001440}
1441
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001442static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001443 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001444 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001445}
1446
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001447// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1448// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1449// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001450static InputEventInjectionResult injectKeyDownNoRepeat(
1451 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001452 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001453 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001454 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001455}
1456
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001457static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001458 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001459 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001460}
1461
Garfield Tandf26e862020-07-01 20:18:19 -07001462class PointerBuilder {
1463public:
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001464 PointerBuilder(int32_t id, ToolType toolType) {
Garfield Tandf26e862020-07-01 20:18:19 -07001465 mProperties.clear();
1466 mProperties.id = id;
1467 mProperties.toolType = toolType;
1468 mCoords.clear();
1469 }
1470
1471 PointerBuilder& x(float x) { return axis(AMOTION_EVENT_AXIS_X, x); }
1472
1473 PointerBuilder& y(float y) { return axis(AMOTION_EVENT_AXIS_Y, y); }
1474
1475 PointerBuilder& axis(int32_t axis, float value) {
1476 mCoords.setAxisValue(axis, value);
1477 return *this;
1478 }
1479
1480 PointerProperties buildProperties() const { return mProperties; }
1481
1482 PointerCoords buildCoords() const { return mCoords; }
1483
1484private:
1485 PointerProperties mProperties;
1486 PointerCoords mCoords;
1487};
1488
1489class MotionEventBuilder {
1490public:
1491 MotionEventBuilder(int32_t action, int32_t source) {
1492 mAction = action;
1493 mSource = source;
1494 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001495 mDownTime = mEventTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001496 }
1497
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001498 MotionEventBuilder& deviceId(int32_t deviceId) {
1499 mDeviceId = deviceId;
1500 return *this;
1501 }
1502
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001503 MotionEventBuilder& downTime(nsecs_t downTime) {
1504 mDownTime = downTime;
1505 return *this;
1506 }
1507
Garfield Tandf26e862020-07-01 20:18:19 -07001508 MotionEventBuilder& eventTime(nsecs_t eventTime) {
1509 mEventTime = eventTime;
1510 return *this;
1511 }
1512
1513 MotionEventBuilder& displayId(int32_t displayId) {
1514 mDisplayId = displayId;
1515 return *this;
1516 }
1517
1518 MotionEventBuilder& actionButton(int32_t actionButton) {
1519 mActionButton = actionButton;
1520 return *this;
1521 }
1522
arthurhung6d4bed92021-03-17 11:59:33 +08001523 MotionEventBuilder& buttonState(int32_t buttonState) {
1524 mButtonState = buttonState;
Garfield Tandf26e862020-07-01 20:18:19 -07001525 return *this;
1526 }
1527
1528 MotionEventBuilder& rawXCursorPosition(float rawXCursorPosition) {
1529 mRawXCursorPosition = rawXCursorPosition;
1530 return *this;
1531 }
1532
1533 MotionEventBuilder& rawYCursorPosition(float rawYCursorPosition) {
1534 mRawYCursorPosition = rawYCursorPosition;
1535 return *this;
1536 }
1537
1538 MotionEventBuilder& pointer(PointerBuilder pointer) {
1539 mPointers.push_back(pointer);
1540 return *this;
1541 }
1542
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001543 MotionEventBuilder& addFlag(uint32_t flags) {
1544 mFlags |= flags;
1545 return *this;
1546 }
1547
Garfield Tandf26e862020-07-01 20:18:19 -07001548 MotionEvent build() {
1549 std::vector<PointerProperties> pointerProperties;
1550 std::vector<PointerCoords> pointerCoords;
1551 for (const PointerBuilder& pointer : mPointers) {
1552 pointerProperties.push_back(pointer.buildProperties());
1553 pointerCoords.push_back(pointer.buildCoords());
1554 }
1555
1556 // Set mouse cursor position for the most common cases to avoid boilerplate.
1557 if (mSource == AINPUT_SOURCE_MOUSE &&
Siarhei Vishniakou70c6ee82023-05-15 17:43:48 -07001558 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) {
Garfield Tandf26e862020-07-01 20:18:19 -07001559 mRawXCursorPosition = pointerCoords[0].getX();
1560 mRawYCursorPosition = pointerCoords[0].getY();
1561 }
1562
1563 MotionEvent event;
chaviw9eaa22c2020-07-01 16:21:27 -07001564 ui::Transform identityTransform;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001565 event.initialize(InputEvent::nextId(), mDeviceId, mSource, mDisplayId, INVALID_HMAC,
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001566 mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
chaviw9eaa22c2020-07-01 16:21:27 -07001567 mButtonState, MotionClassification::NONE, identityTransform,
1568 /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001569 mRawYCursorPosition, identityTransform, mDownTime, mEventTime,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07001570 mPointers.size(), pointerProperties.data(), pointerCoords.data());
Garfield Tandf26e862020-07-01 20:18:19 -07001571
1572 return event;
1573 }
1574
1575private:
1576 int32_t mAction;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08001577 int32_t mDeviceId = DEVICE_ID;
Garfield Tandf26e862020-07-01 20:18:19 -07001578 int32_t mSource;
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001579 nsecs_t mDownTime;
Garfield Tandf26e862020-07-01 20:18:19 -07001580 nsecs_t mEventTime;
1581 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1582 int32_t mActionButton{0};
1583 int32_t mButtonState{0};
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08001584 int32_t mFlags{0};
Garfield Tandf26e862020-07-01 20:18:19 -07001585 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1586 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1587
1588 std::vector<PointerBuilder> mPointers;
1589};
1590
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001591class MotionArgsBuilder {
1592public:
1593 MotionArgsBuilder(int32_t action, int32_t source) {
1594 mAction = action;
1595 mSource = source;
1596 mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
1597 mDownTime = mEventTime;
1598 }
1599
1600 MotionArgsBuilder& deviceId(int32_t deviceId) {
1601 mDeviceId = deviceId;
1602 return *this;
1603 }
1604
1605 MotionArgsBuilder& downTime(nsecs_t downTime) {
1606 mDownTime = downTime;
1607 return *this;
1608 }
1609
1610 MotionArgsBuilder& eventTime(nsecs_t eventTime) {
1611 mEventTime = eventTime;
1612 return *this;
1613 }
1614
1615 MotionArgsBuilder& displayId(int32_t displayId) {
1616 mDisplayId = displayId;
1617 return *this;
1618 }
1619
1620 MotionArgsBuilder& policyFlags(int32_t policyFlags) {
1621 mPolicyFlags = policyFlags;
1622 return *this;
1623 }
1624
1625 MotionArgsBuilder& actionButton(int32_t actionButton) {
1626 mActionButton = actionButton;
1627 return *this;
1628 }
1629
1630 MotionArgsBuilder& buttonState(int32_t buttonState) {
1631 mButtonState = buttonState;
1632 return *this;
1633 }
1634
1635 MotionArgsBuilder& rawXCursorPosition(float rawXCursorPosition) {
1636 mRawXCursorPosition = rawXCursorPosition;
1637 return *this;
1638 }
1639
1640 MotionArgsBuilder& rawYCursorPosition(float rawYCursorPosition) {
1641 mRawYCursorPosition = rawYCursorPosition;
1642 return *this;
1643 }
1644
1645 MotionArgsBuilder& pointer(PointerBuilder pointer) {
1646 mPointers.push_back(pointer);
1647 return *this;
1648 }
1649
1650 MotionArgsBuilder& addFlag(uint32_t flags) {
1651 mFlags |= flags;
1652 return *this;
1653 }
1654
Harry Cuttsb166c002023-05-09 13:06:05 +00001655 MotionArgsBuilder& classification(MotionClassification classification) {
1656 mClassification = classification;
1657 return *this;
1658 }
1659
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001660 NotifyMotionArgs build() {
1661 std::vector<PointerProperties> pointerProperties;
1662 std::vector<PointerCoords> pointerCoords;
1663 for (const PointerBuilder& pointer : mPointers) {
1664 pointerProperties.push_back(pointer.buildProperties());
1665 pointerCoords.push_back(pointer.buildCoords());
1666 }
1667
1668 // Set mouse cursor position for the most common cases to avoid boilerplate.
1669 if (mSource == AINPUT_SOURCE_MOUSE &&
Siarhei Vishniakou70c6ee82023-05-15 17:43:48 -07001670 !MotionEvent::isValidCursorPosition(mRawXCursorPosition, mRawYCursorPosition)) {
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001671 mRawXCursorPosition = pointerCoords[0].getX();
1672 mRawYCursorPosition = pointerCoords[0].getY();
1673 }
1674
1675 NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
1676 mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
Harry Cuttsb166c002023-05-09 13:06:05 +00001677 AMETA_NONE, mButtonState, mClassification, /*edgeFlags=*/0,
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001678 mPointers.size(), pointerProperties.data(), pointerCoords.data(),
1679 /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
1680 mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
1681
1682 return args;
1683 }
1684
1685private:
1686 int32_t mAction;
1687 int32_t mDeviceId = DEVICE_ID;
1688 int32_t mSource;
1689 nsecs_t mDownTime;
1690 nsecs_t mEventTime;
1691 int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
1692 int32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
1693 int32_t mActionButton{0};
1694 int32_t mButtonState{0};
1695 int32_t mFlags{0};
Harry Cuttsb166c002023-05-09 13:06:05 +00001696 MotionClassification mClassification{MotionClassification::NONE};
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001697 float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1698 float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
1699
1700 std::vector<PointerBuilder> mPointers;
1701};
1702
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001703static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001704 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001705 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001706 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1707 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1708 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1709 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001710}
1711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001712static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001713 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001714 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001715 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001716 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1717 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001719 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1720 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001721 MotionEventBuilder motionBuilder =
1722 MotionEventBuilder(action, source)
1723 .displayId(displayId)
1724 .eventTime(eventTime)
1725 .rawXCursorPosition(cursorPosition.x)
1726 .rawYCursorPosition(cursorPosition.y)
1727 .pointer(
1728 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1729 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1730 motionBuilder.downTime(eventTime);
1731 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001732
1733 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001734 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1735 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001736}
1737
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001738static InputEventInjectionResult injectMotionDown(
1739 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1740 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001741 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001742}
1743
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001744static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001745 int32_t source, int32_t displayId,
1746 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001747 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001748}
1749
Jackal Guof9696682018-10-05 12:23:23 +08001750static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1751 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1752 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001753 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001754 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1755 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001756
1757 return args;
1758}
1759
Josep del Riob3981622023-04-18 15:49:45 +00001760static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1761 int32_t displayId = ADISPLAY_ID_NONE) {
1762 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1763 // Define a valid key event.
1764 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1765 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1766 currentTime);
1767
1768 return args;
1769}
1770
1771static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1772 int32_t displayId = ADISPLAY_ID_NONE) {
1773 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1774 // Define a valid key event.
1775 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1776 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1777 AMETA_NONE, currentTime);
1778
1779 return args;
1780}
1781
Prabir Pradhan678438e2023-04-13 19:32:51 +00001782[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1783 int32_t displayId,
1784 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001785 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001786 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1787 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1788 }
1789
chaviwd1c23182019-12-20 18:44:56 -08001790 PointerProperties pointerProperties[pointerCount];
1791 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001792
chaviwd1c23182019-12-20 18:44:56 -08001793 for (size_t i = 0; i < pointerCount; i++) {
1794 pointerProperties[i].clear();
1795 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001796 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001797
chaviwd1c23182019-12-20 18:44:56 -08001798 pointerCoords[i].clear();
1799 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1800 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1801 }
Jackal Guof9696682018-10-05 12:23:23 +08001802
1803 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1804 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001805 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001806 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1807 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001808 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1809 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001810 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1811 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001812
1813 return args;
1814}
1815
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001816static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1817 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1818}
1819
chaviwd1c23182019-12-20 18:44:56 -08001820static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1821 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1822}
1823
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001824static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1825 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001826 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001827}
1828
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001829/**
1830 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1831 * broken channel.
1832 */
1833TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1835 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle>::make(application, mDispatcher,
1837 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001838
1839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1840
1841 // Window closes its channel, but the window remains.
1842 window->destroyReceiver();
1843 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1844}
1845
Arthur Hungb92218b2018-08-14 12:00:21 +08001846TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001848 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1849 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001850
Arthur Hung72d8dc32020-03-28 00:48:39 +00001851 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1853 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1854 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001855
1856 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001857 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001858}
1859
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001860TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1863 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001864
1865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1866 // Inject a MotionEvent to an unknown display.
1867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1868 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1869 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1870
1871 // Window should receive motion event.
1872 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1873}
1874
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001875/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001876 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001877 * This test serves as a sanity check for the next test, where setInputWindows is
1878 * called twice.
1879 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001880TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1883 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001884 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001885
1886 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001887 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001888 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1889 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001890 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001891
1892 // Window should receive motion event.
1893 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1894}
1895
1896/**
1897 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001898 */
1899TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001901 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1902 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001903 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001904
1905 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1906 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001908 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1909 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001911
1912 // Window should receive motion event.
1913 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1914}
1915
Arthur Hungb92218b2018-08-14 12:00:21 +08001916// The foreground window should receive the first touch down event.
1917TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001919 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001920 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001921 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001922 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001923
Arthur Hung72d8dc32020-03-28 00:48:39 +00001924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1926 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001928
1929 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001930 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001931 windowSecond->assertNoEvents();
1932}
1933
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934/**
1935 * Two windows: A top window, and a wallpaper behind the window.
1936 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1937 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001938 * 1. foregroundWindow <-- dup touch to wallpaper
1939 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001940 */
1941TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1943 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001944 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001945 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001948 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001949
1950 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1952 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1953 {100, 200}))
1954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1955
1956 // Both foreground window and its wallpaper should receive the touch down
1957 foregroundWindow->consumeMotionDown();
1958 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1959
1960 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1961 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1962 ADISPLAY_ID_DEFAULT, {110, 200}))
1963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1964
1965 foregroundWindow->consumeMotionMove();
1966 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1967
1968 // Now the foreground window goes away, but the wallpaper stays
1969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1970 foregroundWindow->consumeMotionCancel();
1971 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1972 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973}
1974
1975/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001976 * Two fingers down on the window, and lift off the first finger.
1977 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1978 * contains a single pointer.
1979 */
1980TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1982 sp<FakeWindowHandle> window =
1983 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1984
1985 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001986 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1988 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1989 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001990 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001991 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1992 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1993 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1994 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001995 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001996 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1997 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1998 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1999 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002000 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2001 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2002 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2003
2004 // Remove the window. The gesture should be canceled
2005 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
2006 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
2007 window->consumeMotionEvent(
2008 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
2009}
2010
2011/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002012 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
2013 * with the following differences:
2014 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
2015 * clean up the connection.
2016 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
2017 * Ensure that there's no crash in the dispatcher.
2018 */
2019TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
2020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2021 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002022 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002023 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002024 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002025 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002026 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002027
2028 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
2029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2030 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2031 {100, 200}))
2032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2033
2034 // Both foreground window and its wallpaper should receive the touch down
2035 foregroundWindow->consumeMotionDown();
2036 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2037
2038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2039 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2040 ADISPLAY_ID_DEFAULT, {110, 200}))
2041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2042
2043 foregroundWindow->consumeMotionMove();
2044 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2045
2046 // Wallpaper closes its channel, but the window remains.
2047 wallpaperWindow->destroyReceiver();
2048 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
2049
2050 // Now the foreground window goes away, but the wallpaper stays, even though its channel
2051 // is no longer valid.
2052 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
2053 foregroundWindow->consumeMotionCancel();
2054}
2055
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056class ShouldSplitTouchFixture : public InputDispatcherTest,
2057 public ::testing::WithParamInterface<bool> {};
2058INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2059 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002060/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002061 * A single window that receives touch (on top), and a wallpaper window underneath it.
2062 * The top window gets a multitouch gesture.
2063 * Ensure that wallpaper gets the same gesture.
2064 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002065TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002067 sp<FakeWindowHandle> foregroundWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2069 foregroundWindow->setDupTouchToWallpaper(true);
2070 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002071
2072 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002073 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002074 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002075
Arthur Hungc539dbb2022-12-08 07:45:36 +00002076 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002077
2078 // Touch down on top window
2079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2080 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2081 {100, 100}))
2082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2083
2084 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002085 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002086 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2087
2088 // Second finger down on the top window
2089 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002090 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002091 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002092 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2093 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094 .build();
2095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2096 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2097 InputEventInjectionSync::WAIT_FOR_RESULT))
2098 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2099
Harry Cutts33476232023-01-30 19:57:29 +00002100 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2101 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002103
2104 const MotionEvent secondFingerUpEvent =
2105 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2106 .displayId(ADISPLAY_ID_DEFAULT)
2107 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002108 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2109 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002110 .build();
2111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2112 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
2113 InputEventInjectionSync::WAIT_FOR_RESULT))
2114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2115 foregroundWindow->consumeMotionPointerUp(0);
2116 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2117
2118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002119 injectMotionEvent(mDispatcher,
2120 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2121 AINPUT_SOURCE_TOUCHSCREEN)
2122 .displayId(ADISPLAY_ID_DEFAULT)
2123 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
2124 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002125 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002126 .x(100)
2127 .y(100))
2128 .build(),
2129 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002130 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2131 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2132 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002133}
2134
2135/**
2136 * Two windows: a window on the left and window on the right.
2137 * A third window, wallpaper, is behind both windows, and spans both top windows.
2138 * The first touch down goes to the left window. A second pointer touches down on the right window.
2139 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2140 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2141 * ACTION_POINTER_DOWN(1).
2142 */
2143TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2144 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2145 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002146 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002147 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002148 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002149
2150 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002151 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002152 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002153 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002154
2155 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002156 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002157 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002158 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002159
2160 mDispatcher->setInputWindows(
2161 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
2162
2163 // Touch down on left window
2164 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2165 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
2166 {100, 100}))
2167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2168
2169 // Both foreground window and its wallpaper should receive the touch down
2170 leftWindow->consumeMotionDown();
2171 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2172
2173 // Second finger down on the right window
2174 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002175 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002176 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002177 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2178 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002179 .build();
2180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2181 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
2182 InputEventInjectionSync::WAIT_FOR_RESULT))
2183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2184
2185 leftWindow->consumeMotionMove();
2186 // Since the touch is split, right window gets ACTION_DOWN
2187 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002188 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002189 expectedWallpaperFlags);
2190
2191 // Now, leftWindow, which received the first finger, disappears.
2192 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2193 leftWindow->consumeMotionCancel();
2194 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2195 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2196
2197 // The pointer that's still down on the right window moves, and goes to the right window only.
2198 // As far as the dispatcher's concerned though, both pointers are still present.
2199 const MotionEvent secondFingerMoveEvent =
2200 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2201 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002202 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2203 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002204 .build();
2205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2206 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2207 InputEventInjectionSync::WAIT_FOR_RESULT));
2208 rightWindow->consumeMotionMove();
2209
2210 leftWindow->assertNoEvents();
2211 rightWindow->assertNoEvents();
2212 wallpaperWindow->assertNoEvents();
2213}
2214
Arthur Hungc539dbb2022-12-08 07:45:36 +00002215/**
2216 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2217 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2218 * The right window should receive ACTION_DOWN.
2219 */
2220TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002222 sp<FakeWindowHandle> leftWindow =
2223 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2224 leftWindow->setFrame(Rect(0, 0, 200, 200));
2225 leftWindow->setDupTouchToWallpaper(true);
2226 leftWindow->setSlippery(true);
2227
2228 sp<FakeWindowHandle> rightWindow =
2229 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2230 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002231
2232 sp<FakeWindowHandle> wallpaperWindow =
2233 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2234 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002235
Arthur Hungc539dbb2022-12-08 07:45:36 +00002236 mDispatcher->setInputWindows(
2237 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002238
Arthur Hungc539dbb2022-12-08 07:45:36 +00002239 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2241 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002242 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002244
2245 // Both foreground window and its wallpaper should receive the touch down
2246 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002247 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2248
Arthur Hungc539dbb2022-12-08 07:45:36 +00002249 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002251 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2252 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2254
Arthur Hungc539dbb2022-12-08 07:45:36 +00002255 leftWindow->consumeMotionCancel();
2256 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2257 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002258}
2259
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002260/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002261 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2262 * interactive, it might stop sending this flag.
2263 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2264 * to have a consistent input stream.
2265 *
2266 * Test procedure:
2267 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2268 * DOWN (new gesture).
2269 *
2270 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2271 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2272 *
2273 * We technically just need a single window here, but we are using two windows (spy on top and a
2274 * regular window below) to emulate the actual situation where it happens on the device.
2275 */
2276TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2278 sp<FakeWindowHandle> spyWindow =
2279 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2280 spyWindow->setFrame(Rect(0, 0, 200, 200));
2281 spyWindow->setTrustedOverlay(true);
2282 spyWindow->setSpy(true);
2283
2284 sp<FakeWindowHandle> window =
2285 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2286 window->setFrame(Rect(0, 0, 200, 200));
2287
2288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2289 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002290
2291 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002292 mDispatcher->notifyMotion(
2293 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2294 .deviceId(touchDeviceId)
2295 .policyFlags(DEFAULT_POLICY_FLAGS)
2296 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2297 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002298
Prabir Pradhan678438e2023-04-13 19:32:51 +00002299 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2300 .deviceId(touchDeviceId)
2301 .policyFlags(DEFAULT_POLICY_FLAGS)
2302 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2303 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2304 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002305 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2306 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2307 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2308 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2309
2310 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002311 mDispatcher->notifyMotion(
2312 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2313 .deviceId(touchDeviceId)
2314 .policyFlags(0)
2315 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2316 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2317 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002318 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2319 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2320
2321 // We don't need to reset the device to reproduce the issue, but the reset event typically
2322 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002323 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002324
2325 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002326 mDispatcher->notifyMotion(
2327 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2328 .deviceId(touchDeviceId)
2329 .policyFlags(DEFAULT_POLICY_FLAGS)
2330 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2331 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002332 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2333 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2334
2335 // No more events
2336 spyWindow->assertNoEvents();
2337 window->assertNoEvents();
2338}
2339
2340/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002341 * Two windows: a window on the left and a window on the right.
2342 * Mouse is hovered from the right window into the left window.
2343 * Next, we tap on the left window, where the cursor was last seen.
2344 * The second tap is done onto the right window.
2345 * The mouse and tap are from two different devices.
2346 * We technically don't need to set the downtime / eventtime for these events, but setting these
2347 * explicitly helps during debugging.
2348 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2349 * In the buggy implementation, a tap on the right window would cause a crash.
2350 */
2351TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2353 sp<FakeWindowHandle> leftWindow =
2354 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2355 leftWindow->setFrame(Rect(0, 0, 200, 200));
2356
2357 sp<FakeWindowHandle> rightWindow =
2358 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2359 rightWindow->setFrame(Rect(200, 0, 400, 200));
2360
2361 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2362 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2363 // stale.
2364 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2365 const int32_t mouseDeviceId = 6;
2366 const int32_t touchDeviceId = 4;
2367 // Move the cursor from right
2368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2369 injectMotionEvent(mDispatcher,
2370 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2371 AINPUT_SOURCE_MOUSE)
2372 .deviceId(mouseDeviceId)
2373 .downTime(baseTime + 10)
2374 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002375 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002376 .x(300)
2377 .y(100))
2378 .build()));
2379 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2380
2381 // .. to the left window
2382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2383 injectMotionEvent(mDispatcher,
2384 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2385 AINPUT_SOURCE_MOUSE)
2386 .deviceId(mouseDeviceId)
2387 .downTime(baseTime + 10)
2388 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002389 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002390 .x(110)
2391 .y(100))
2392 .build()));
2393 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2394 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2395 // Now tap the left window
2396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2397 injectMotionEvent(mDispatcher,
2398 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2399 AINPUT_SOURCE_TOUCHSCREEN)
2400 .deviceId(touchDeviceId)
2401 .downTime(baseTime + 40)
2402 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002403 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002404 .x(100)
2405 .y(100))
2406 .build()));
2407 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2408 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2409
2410 // release tap
2411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2412 injectMotionEvent(mDispatcher,
2413 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2414 AINPUT_SOURCE_TOUCHSCREEN)
2415 .deviceId(touchDeviceId)
2416 .downTime(baseTime + 40)
2417 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002418 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002419 .x(100)
2420 .y(100))
2421 .build()));
2422 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2423
2424 // Tap the window on the right
2425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2426 injectMotionEvent(mDispatcher,
2427 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2428 AINPUT_SOURCE_TOUCHSCREEN)
2429 .deviceId(touchDeviceId)
2430 .downTime(baseTime + 60)
2431 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002432 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002433 .x(300)
2434 .y(100))
2435 .build()));
2436 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2437
2438 // release tap
2439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2440 injectMotionEvent(mDispatcher,
2441 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2442 AINPUT_SOURCE_TOUCHSCREEN)
2443 .deviceId(touchDeviceId)
2444 .downTime(baseTime + 60)
2445 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002446 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002447 .x(300)
2448 .y(100))
2449 .build()));
2450 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2451
2452 // No more events
2453 leftWindow->assertNoEvents();
2454 rightWindow->assertNoEvents();
2455}
2456
2457/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002458 * Start hovering in a window. While this hover is still active, make another window appear on top.
2459 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2460 * While the top window is present, the hovering is stopped.
2461 * Later, hovering gets resumed again.
2462 * Ensure that new hover gesture is handled correctly.
2463 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2464 * to the window that's currently being hovered over.
2465 */
2466TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2468 sp<FakeWindowHandle> window =
2469 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2470 window->setFrame(Rect(0, 0, 200, 200));
2471
2472 // Only a single window is present at first
2473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2474
2475 // Start hovering in the window
2476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2477 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2478 .build());
2479 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2480
2481 // Now, an obscuring window appears!
2482 sp<FakeWindowHandle> obscuringWindow =
2483 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2484 ADISPLAY_ID_DEFAULT,
2485 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2486 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2487 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2488 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2489 obscuringWindow->setNoInputChannel(true);
2490 obscuringWindow->setFocusable(false);
2491 obscuringWindow->setAlpha(1.0);
2492 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2493
2494 // While this new obscuring window is present, the hovering is stopped
2495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2496 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2497 .build());
2498 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2499
2500 // Now the obscuring window goes away.
2501 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2502
2503 // And a new hover gesture starts.
2504 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2505 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2506 .build());
2507 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2508}
2509
2510/**
2511 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2512 * the obscuring window.
2513 */
2514TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2516 sp<FakeWindowHandle> window =
2517 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2518 window->setFrame(Rect(0, 0, 200, 200));
2519
2520 // Only a single window is present at first
2521 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2522
2523 // Start hovering in the window
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2525 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2526 .build());
2527 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2528
2529 // Now, an obscuring window appears!
2530 sp<FakeWindowHandle> obscuringWindow =
2531 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2532 ADISPLAY_ID_DEFAULT,
2533 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2534 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2535 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2536 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2537 obscuringWindow->setNoInputChannel(true);
2538 obscuringWindow->setFocusable(false);
2539 obscuringWindow->setAlpha(1.0);
2540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2541
2542 // While this new obscuring window is present, the hovering continues. The event can't go to the
2543 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2544 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2545 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2546 .build());
2547 obscuringWindow->assertNoEvents();
2548 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2549
2550 // Now the obscuring window goes away.
2551 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2552
2553 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2554 // so it should generate a HOVER_ENTER
2555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2556 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2557 .build());
2558 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2559
2560 // Now the MOVE should be getting dispatched normally
2561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2562 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2563 .build());
2564 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2565}
2566
2567/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002568 * Two windows: a window on the left and a window on the right.
2569 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2570 * down. Then, on the left window, also place second touch pointer down.
2571 * This test tries to reproduce a crash.
2572 * In the buggy implementation, second pointer down on the left window would cause a crash.
2573 */
2574TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2576 sp<FakeWindowHandle> leftWindow =
2577 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2578 leftWindow->setFrame(Rect(0, 0, 200, 200));
2579
2580 sp<FakeWindowHandle> rightWindow =
2581 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2582 rightWindow->setFrame(Rect(200, 0, 400, 200));
2583
2584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2585
2586 const int32_t touchDeviceId = 4;
2587 const int32_t mouseDeviceId = 6;
2588 NotifyMotionArgs args;
2589
2590 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2592 .deviceId(mouseDeviceId)
2593 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2594 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002595 leftWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2597
2598 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2600 .deviceId(mouseDeviceId)
2601 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2602 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2603 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002604
2605 leftWindow->consumeMotionEvent(
2606 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2607 leftWindow->consumeMotionEvent(
2608 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2609
Prabir Pradhan678438e2023-04-13 19:32:51 +00002610 mDispatcher->notifyMotion(
2611 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2612 .deviceId(mouseDeviceId)
2613 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2614 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2615 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2616 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002617 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2618
2619 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2623 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002624 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2625
2626 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2627
2628 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002629 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2630 .deviceId(touchDeviceId)
2631 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2632 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2633 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002634 leftWindow->consumeMotionEvent(
2635 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2636 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2637 // current implementation.
2638 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2639 rightWindow->consumeMotionEvent(
2640 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2641
2642 leftWindow->assertNoEvents();
2643 rightWindow->assertNoEvents();
2644}
2645
2646/**
2647 * On a single window, use two different devices: mouse and touch.
2648 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2649 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2650 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2651 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2652 * represent a new gesture.
2653 */
2654TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2655 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2656 sp<FakeWindowHandle> window =
2657 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2658 window->setFrame(Rect(0, 0, 400, 400));
2659
2660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2661
2662 const int32_t touchDeviceId = 4;
2663 const int32_t mouseDeviceId = 6;
2664 NotifyMotionArgs args;
2665
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002666 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002667 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2668 .deviceId(touchDeviceId)
2669 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2670 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002671 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002672 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2675 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002677 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002678 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2679 .deviceId(touchDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2681 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2682 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002683 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2684 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2685 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2686
2687 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2689 .deviceId(mouseDeviceId)
2690 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2691 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2692 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002693
2694 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002695 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002696 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2697
Prabir Pradhan678438e2023-04-13 19:32:51 +00002698 mDispatcher->notifyMotion(
2699 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2700 .deviceId(mouseDeviceId)
2701 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2702 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2703 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2704 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002705 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2706
2707 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002708 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2709 .deviceId(touchDeviceId)
2710 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2711 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2712 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002713 // The pointer_down event should be ignored
2714 window->assertNoEvents();
2715}
2716
2717/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002718 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2719 * the injected event.
2720 */
2721TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2722 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2723 sp<FakeWindowHandle> window =
2724 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2725 window->setFrame(Rect(0, 0, 400, 400));
2726
2727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2728
2729 const int32_t touchDeviceId = 4;
2730 NotifyMotionArgs args;
2731 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2732 // completion.
2733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2734 injectMotionEvent(mDispatcher,
2735 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2736 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002737 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002738 .x(50)
2739 .y(50))
2740 .build()));
2741 window->consumeMotionEvent(
2742 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2743
2744 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2745 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2747 .deviceId(touchDeviceId)
2748 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2749 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002750
2751 window->consumeMotionEvent(
2752 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2753 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2754}
2755
2756/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002757 * This test is similar to the test above, but the sequence of injected events is different.
2758 *
2759 * Two windows: a window on the left and a window on the right.
2760 * Mouse is hovered over the left window.
2761 * Next, we tap on the left window, where the cursor was last seen.
2762 *
2763 * After that, we inject one finger down onto the right window, and then a second finger down onto
2764 * the left window.
2765 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2766 * window (first), and then another on the left window (second).
2767 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2768 * In the buggy implementation, second finger down on the left window would cause a crash.
2769 */
2770TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2772 sp<FakeWindowHandle> leftWindow =
2773 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2774 leftWindow->setFrame(Rect(0, 0, 200, 200));
2775
2776 sp<FakeWindowHandle> rightWindow =
2777 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2778 rightWindow->setFrame(Rect(200, 0, 400, 200));
2779
2780 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2781
2782 const int32_t mouseDeviceId = 6;
2783 const int32_t touchDeviceId = 4;
2784 // Hover over the left window. Keep the cursor there.
2785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2786 injectMotionEvent(mDispatcher,
2787 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2788 AINPUT_SOURCE_MOUSE)
2789 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002790 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002791 .x(50)
2792 .y(50))
2793 .build()));
2794 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2795
2796 // Tap on left window
2797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2798 injectMotionEvent(mDispatcher,
2799 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2800 AINPUT_SOURCE_TOUCHSCREEN)
2801 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002802 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002803 .x(100)
2804 .y(100))
2805 .build()));
2806
2807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2808 injectMotionEvent(mDispatcher,
2809 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2810 AINPUT_SOURCE_TOUCHSCREEN)
2811 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002812 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002813 .x(100)
2814 .y(100))
2815 .build()));
2816 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2817 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2818 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2819
2820 // First finger down on right window
2821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2822 injectMotionEvent(mDispatcher,
2823 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2824 AINPUT_SOURCE_TOUCHSCREEN)
2825 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002826 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002827 .x(300)
2828 .y(100))
2829 .build()));
2830 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2831
2832 // Second finger down on the left window
2833 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2834 injectMotionEvent(mDispatcher,
2835 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2836 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002837 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002838 .x(300)
2839 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002840 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002841 .x(100)
2842 .y(100))
2843 .build()));
2844 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2845 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2846
2847 // No more events
2848 leftWindow->assertNoEvents();
2849 rightWindow->assertNoEvents();
2850}
2851
2852/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002853 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2854 * While the touch is down, new hover events from the stylus device should be ignored. After the
2855 * touch is gone, stylus hovering should start working again.
2856 */
2857TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2858 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2859 sp<FakeWindowHandle> window =
2860 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2861 window->setFrame(Rect(0, 0, 200, 200));
2862
2863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2864
2865 const int32_t stylusDeviceId = 5;
2866 const int32_t touchDeviceId = 4;
2867 // Start hovering with stylus
2868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2869 injectMotionEvent(mDispatcher,
2870 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2871 AINPUT_SOURCE_STYLUS)
2872 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002873 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002874 .x(50)
2875 .y(50))
2876 .build()));
2877 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2878
2879 // Finger down on the window
2880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2881 injectMotionEvent(mDispatcher,
2882 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2883 AINPUT_SOURCE_TOUCHSCREEN)
2884 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002885 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002886 .x(100)
2887 .y(100))
2888 .build()));
2889 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2890 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2891
2892 // Try to continue hovering with stylus. Since we are already down, injection should fail
2893 ASSERT_EQ(InputEventInjectionResult::FAILED,
2894 injectMotionEvent(mDispatcher,
2895 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2896 AINPUT_SOURCE_STYLUS)
2897 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002898 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002899 .x(50)
2900 .y(50))
2901 .build()));
2902 // No event should be sent. This event should be ignored because a pointer from another device
2903 // is already down.
2904
2905 // Lift up the finger
2906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2907 injectMotionEvent(mDispatcher,
2908 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2909 AINPUT_SOURCE_TOUCHSCREEN)
2910 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002911 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002912 .x(100)
2913 .y(100))
2914 .build()));
2915 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2916
2917 // Now that the touch is gone, stylus hovering should start working again
2918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2919 injectMotionEvent(mDispatcher,
2920 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2921 AINPUT_SOURCE_STYLUS)
2922 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002923 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002924 .x(50)
2925 .y(50))
2926 .build()));
2927 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2928 // No more events
2929 window->assertNoEvents();
2930}
2931
2932/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002933 * A spy window above a window with no input channel.
2934 * Start hovering with a stylus device, and then tap with it.
2935 * Ensure spy window receives the entire sequence.
2936 */
2937TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2938 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2939 sp<FakeWindowHandle> spyWindow =
2940 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2941 spyWindow->setFrame(Rect(0, 0, 200, 200));
2942 spyWindow->setTrustedOverlay(true);
2943 spyWindow->setSpy(true);
2944 sp<FakeWindowHandle> window =
2945 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2946 window->setNoInputChannel(true);
2947 window->setFrame(Rect(0, 0, 200, 200));
2948
2949 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2950
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002951 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2953 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2954 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002955 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2956 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2958 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2959 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002960 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2961
2962 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2964 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2965 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002966 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2967
2968 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2970 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2971 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002972 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2973
2974 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2976 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2977 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002978 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2979 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002980 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2981 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2982 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002983 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2984
2985 // No more events
2986 spyWindow->assertNoEvents();
2987 window->assertNoEvents();
2988}
2989
2990/**
2991 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2992 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2993 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2994 * While the mouse is down, new move events from the touch device should be ignored.
2995 */
2996TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2998 sp<FakeWindowHandle> spyWindow =
2999 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3000 spyWindow->setFrame(Rect(0, 0, 200, 200));
3001 spyWindow->setTrustedOverlay(true);
3002 spyWindow->setSpy(true);
3003 sp<FakeWindowHandle> window =
3004 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3005 window->setFrame(Rect(0, 0, 200, 200));
3006
3007 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3008
3009 const int32_t mouseDeviceId = 7;
3010 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003011
3012 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3014 .deviceId(mouseDeviceId)
3015 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3016 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003017 spyWindow->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3019 window->consumeMotionEvent(
3020 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3021
3022 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003023 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3024 .deviceId(touchDeviceId)
3025 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3026 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003027 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3028 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3029 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3030 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3031
Prabir Pradhan678438e2023-04-13 19:32:51 +00003032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3033 .deviceId(touchDeviceId)
3034 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3035 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003036 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3037 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3038
3039 // Pilfer the stream
3040 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3041 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3042
Prabir Pradhan678438e2023-04-13 19:32:51 +00003043 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3044 .deviceId(touchDeviceId)
3045 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3046 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003047 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3048
3049 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3051 .deviceId(mouseDeviceId)
3052 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3054 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003055
3056 spyWindow->consumeMotionEvent(
3057 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3058 spyWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3060 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3061
Prabir Pradhan678438e2023-04-13 19:32:51 +00003062 mDispatcher->notifyMotion(
3063 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3064 .deviceId(mouseDeviceId)
3065 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3066 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3067 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3068 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003069 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3070 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3071
3072 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003073 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3074 .deviceId(mouseDeviceId)
3075 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3076 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3077 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003078 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3079 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3080
3081 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3083 .deviceId(touchDeviceId)
3084 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3085 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003086
3087 // No more events
3088 spyWindow->assertNoEvents();
3089 window->assertNoEvents();
3090}
3091
3092/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003093 * On the display, have a single window, and also an area where there's no window.
3094 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3095 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3096 */
3097TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3099 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003100 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003101
3102 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003103
3104 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003105 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003106
3107 mDispatcher->waitForIdle();
3108 window->assertNoEvents();
3109
3110 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003111 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003112 mDispatcher->waitForIdle();
3113 window->consumeMotionDown();
3114}
3115
3116/**
3117 * Same test as above, but instead of touching the empty space, the first touch goes to
3118 * non-touchable window.
3119 */
3120TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3121 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3122 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003123 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003124 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3125 window1->setTouchable(false);
3126 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003127 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003128 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3129
3130 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3131
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003132 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003134
3135 mDispatcher->waitForIdle();
3136 window1->assertNoEvents();
3137 window2->assertNoEvents();
3138
3139 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003140 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003141 mDispatcher->waitForIdle();
3142 window2->consumeMotionDown();
3143}
3144
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003145/**
3146 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3147 * to the event time of the first ACTION_DOWN sent to the particular window.
3148 */
3149TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3151 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003152 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003153 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3154 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003155 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003156 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3157
3158 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
3159
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003160 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003161 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003162
3163 mDispatcher->waitForIdle();
3164 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003165 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003166 window2->assertNoEvents();
3167 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
3168 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
3169 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
3170
3171 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003172 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003173 mDispatcher->waitForIdle();
3174 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003175 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003176 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
3177 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
3178 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
3179 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
3180
3181 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003182 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003183 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003184 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003185
3186 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003187 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003188 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003189 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003190
3191 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3192 window1->consumeMotionMove();
3193 window1->assertNoEvents();
3194
3195 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003196 mDispatcher->notifyMotion(
3197 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003198 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003199 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003200
Prabir Pradhan678438e2023-04-13 19:32:51 +00003201 mDispatcher->notifyMotion(
3202 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003203 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003204 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003205}
3206
Garfield Tandf26e862020-07-01 20:18:19 -07003207TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003208 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003209 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003210 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003211 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003212 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003213 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003214 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003215
3216 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3217
3218 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3219
3220 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003222 injectMotionEvent(mDispatcher,
3223 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3224 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003225 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003226 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003227 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003228
3229 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003231 injectMotionEvent(mDispatcher,
3232 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3233 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003235 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003236 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3237 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003238
3239 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003241 injectMotionEvent(mDispatcher,
3242 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3243 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003244 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003245 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003246 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3247 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003248
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003250 injectMotionEvent(mDispatcher,
3251 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3252 AINPUT_SOURCE_MOUSE)
3253 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3254 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003255 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003256 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003257 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003258
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003260 injectMotionEvent(mDispatcher,
3261 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3262 AINPUT_SOURCE_MOUSE)
3263 .buttonState(0)
3264 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003265 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003266 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003267 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003268
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003270 injectMotionEvent(mDispatcher,
3271 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3272 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003273 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003274 .build()));
3275 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3276
3277 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003279 injectMotionEvent(mDispatcher,
3280 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3281 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003282 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003283 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003284 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003285
3286 // No more events
3287 windowLeft->assertNoEvents();
3288 windowRight->assertNoEvents();
3289}
3290
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003291/**
3292 * Put two fingers down (and don't release them) and click the mouse button.
3293 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3294 * currently active gesture should be canceled, and the new one should proceed.
3295 */
3296TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3298 sp<FakeWindowHandle> window =
3299 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3300 window->setFrame(Rect(0, 0, 600, 800));
3301
3302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3303
3304 const int32_t touchDeviceId = 4;
3305 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003306
3307 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3309 .deviceId(touchDeviceId)
3310 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3311 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003312
Prabir Pradhan678438e2023-04-13 19:32:51 +00003313 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3314 .deviceId(touchDeviceId)
3315 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3316 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3317 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003318 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3319 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3320
3321 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003322 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3323 .deviceId(mouseDeviceId)
3324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3325 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3326 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003327 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3328 WithPointerCount(2u)));
3329 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3330
Prabir Pradhan678438e2023-04-13 19:32:51 +00003331 mDispatcher->notifyMotion(
3332 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3333 .deviceId(mouseDeviceId)
3334 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3335 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3336 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3337 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003338 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3339
3340 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3341 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3343 .deviceId(touchDeviceId)
3344 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3345 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3346 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003347 window->assertNoEvents();
3348}
3349
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003350TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3352
3353 sp<FakeWindowHandle> spyWindow =
3354 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3355 spyWindow->setFrame(Rect(0, 0, 600, 800));
3356 spyWindow->setTrustedOverlay(true);
3357 spyWindow->setSpy(true);
3358 sp<FakeWindowHandle> window =
3359 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3360 window->setFrame(Rect(0, 0, 600, 800));
3361
3362 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3363 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3364
3365 // Send mouse cursor to the window
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3367 injectMotionEvent(mDispatcher,
3368 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3369 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003370 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003371 .x(100)
3372 .y(100))
3373 .build()));
3374
3375 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3376 WithSource(AINPUT_SOURCE_MOUSE)));
3377 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3378 WithSource(AINPUT_SOURCE_MOUSE)));
3379
3380 window->assertNoEvents();
3381 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003382}
3383
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003384TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3386
3387 sp<FakeWindowHandle> spyWindow =
3388 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3389 spyWindow->setFrame(Rect(0, 0, 600, 800));
3390 spyWindow->setTrustedOverlay(true);
3391 spyWindow->setSpy(true);
3392 sp<FakeWindowHandle> window =
3393 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3394 window->setFrame(Rect(0, 0, 600, 800));
3395
3396 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3397 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3398
3399 // Send mouse cursor to the window
3400 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3401 injectMotionEvent(mDispatcher,
3402 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3403 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003404 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003405 .x(100)
3406 .y(100))
3407 .build()));
3408
3409 // Move mouse cursor
3410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3411 injectMotionEvent(mDispatcher,
3412 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3413 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003414 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003415 .x(110)
3416 .y(110))
3417 .build()));
3418
3419 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3420 WithSource(AINPUT_SOURCE_MOUSE)));
3421 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3422 WithSource(AINPUT_SOURCE_MOUSE)));
3423 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3424 WithSource(AINPUT_SOURCE_MOUSE)));
3425 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3426 WithSource(AINPUT_SOURCE_MOUSE)));
3427 // Touch down on the window
3428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3429 injectMotionEvent(mDispatcher,
3430 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3431 AINPUT_SOURCE_TOUCHSCREEN)
3432 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003433 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003434 .x(200)
3435 .y(200))
3436 .build()));
3437 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3438 WithSource(AINPUT_SOURCE_MOUSE)));
3439 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3440 WithSource(AINPUT_SOURCE_MOUSE)));
3441 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3442 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3443 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3444 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3445
3446 // pilfer the motion, retaining the gesture on the spy window.
3447 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3448 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3449 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3450
3451 // Touch UP on the window
3452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3453 injectMotionEvent(mDispatcher,
3454 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3455 AINPUT_SOURCE_TOUCHSCREEN)
3456 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003457 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003458 .x(200)
3459 .y(200))
3460 .build()));
3461 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3462 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3463
3464 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3465 // to send a new gesture. It should again go to both windows (spy and the window below), just
3466 // like the first gesture did, before pilfering. The window configuration has not changed.
3467
3468 // One more tap - DOWN
3469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3470 injectMotionEvent(mDispatcher,
3471 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3472 AINPUT_SOURCE_TOUCHSCREEN)
3473 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003474 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003475 .x(250)
3476 .y(250))
3477 .build()));
3478 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3479 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3480 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3481 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3482
3483 // Touch UP on the window
3484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3485 injectMotionEvent(mDispatcher,
3486 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3487 AINPUT_SOURCE_TOUCHSCREEN)
3488 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003489 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003490 .x(250)
3491 .y(250))
3492 .build()));
3493 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3494 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3495 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3496 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3497
3498 window->assertNoEvents();
3499 spyWindow->assertNoEvents();
3500}
3501
Garfield Tandf26e862020-07-01 20:18:19 -07003502// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3503// directly in this test.
3504TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003505 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003506 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003507 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003508 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003509
3510 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3511
3512 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3513
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003515 injectMotionEvent(mDispatcher,
3516 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3517 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003518 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003519 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003520 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003521 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003523 injectMotionEvent(mDispatcher,
3524 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3525 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003526 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003527 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003528 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3529 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003530
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003532 injectMotionEvent(mDispatcher,
3533 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3534 AINPUT_SOURCE_MOUSE)
3535 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3536 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003537 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003538 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003539 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003540
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003542 injectMotionEvent(mDispatcher,
3543 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3544 AINPUT_SOURCE_MOUSE)
3545 .buttonState(0)
3546 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003547 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003548 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003549 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003550
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003551 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003552 injectMotionEvent(mDispatcher,
3553 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3554 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003555 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003556 .build()));
3557 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3558
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003559 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3560 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3561 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003562 injectMotionEvent(mDispatcher,
3563 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3564 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003565 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003566 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003567 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003568}
3569
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003570/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003571 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3572 * is generated.
3573 */
3574TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3576 sp<FakeWindowHandle> window =
3577 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3578 window->setFrame(Rect(0, 0, 1200, 800));
3579
3580 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3581
3582 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3583
3584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3585 injectMotionEvent(mDispatcher,
3586 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3587 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003588 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003589 .x(300)
3590 .y(400))
3591 .build()));
3592 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3593
3594 // Remove the window, but keep the channel.
3595 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3596 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3597}
3598
3599/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003600 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3601 */
3602TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3604 sp<FakeWindowHandle> window =
3605 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3606 window->setFrame(Rect(0, 0, 100, 100));
3607
3608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3609
3610 const int32_t mouseDeviceId = 7;
3611 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003612
3613 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003614 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3615 .deviceId(mouseDeviceId)
3616 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3617 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003618 window->consumeMotionEvent(
3619 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3620
3621 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3623 .deviceId(touchDeviceId)
3624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3625 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003626
3627 window->consumeMotionEvent(
3628 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3629 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3630}
3631
3632/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003633 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003634 * The tap causes a HOVER_EXIT event to be generated because the current event
3635 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003636 */
3637TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3639 sp<FakeWindowHandle> window =
3640 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3641 window->setFrame(Rect(0, 0, 100, 100));
3642
3643 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3644
3645 // Inject a hover_move from mouse.
3646 NotifyMotionArgs motionArgs =
3647 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3648 ADISPLAY_ID_DEFAULT, {{50, 50}});
3649 motionArgs.xCursorPosition = 50;
3650 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003651 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003652 ASSERT_NO_FATAL_FAILURE(
3653 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3654 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003655
3656 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003657 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3658 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3659 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003660 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003661 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3662 WithSource(AINPUT_SOURCE_MOUSE))));
3663
3664 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003665 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3666 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3667
Prabir Pradhan678438e2023-04-13 19:32:51 +00003668 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3669 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003670 ASSERT_NO_FATAL_FAILURE(
3671 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3672 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3673}
3674
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003675TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3676 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3677 sp<FakeWindowHandle> windowDefaultDisplay =
3678 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3679 ADISPLAY_ID_DEFAULT);
3680 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3681 sp<FakeWindowHandle> windowSecondDisplay =
3682 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3683 SECOND_DISPLAY_ID);
3684 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3685
3686 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3687 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3688
3689 // Set cursor position in window in default display and check that hover enter and move
3690 // events are generated.
3691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3692 injectMotionEvent(mDispatcher,
3693 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3694 AINPUT_SOURCE_MOUSE)
3695 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003696 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003697 .x(300)
3698 .y(600))
3699 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003700 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003701
3702 // Remove all windows in secondary display and check that no event happens on window in
3703 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003704 mDispatcher->setInputWindows(
3705 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003706 windowDefaultDisplay->assertNoEvents();
3707
3708 // Move cursor position in window in default display and check that only hover move
3709 // event is generated and not hover enter event.
3710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3711 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3713 injectMotionEvent(mDispatcher,
3714 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3715 AINPUT_SOURCE_MOUSE)
3716 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003717 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003718 .x(400)
3719 .y(700))
3720 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003721 windowDefaultDisplay->consumeMotionEvent(
3722 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3723 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003724 windowDefaultDisplay->assertNoEvents();
3725}
3726
Garfield Tan00f511d2019-06-12 16:55:40 -07003727TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003729
3730 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003731 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003732 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003733 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003734 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003735 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003736
3737 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3738
Arthur Hung72d8dc32020-03-28 00:48:39 +00003739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003740
3741 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3742 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003744 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003745 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003746 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003747 windowRight->assertNoEvents();
3748}
3749
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003750TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003752 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3753 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003754 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003755
Arthur Hung72d8dc32020-03-28 00:48:39 +00003756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003757 setFocusedWindow(window);
3758
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003759 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003760
Prabir Pradhan678438e2023-04-13 19:32:51 +00003761 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003762
3763 // Window should receive key down event.
3764 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3765
3766 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3767 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003768 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003769 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003770 AKEY_EVENT_FLAG_CANCELED);
3771}
3772
3773TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003775 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3776 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003777
Arthur Hung72d8dc32020-03-28 00:48:39 +00003778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003779
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3781 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003782
3783 // Window should receive motion down event.
3784 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3785
3786 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3787 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003788 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003789 window->consumeMotionEvent(
3790 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003791}
3792
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003793TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3795 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3796 "Fake Window", ADISPLAY_ID_DEFAULT);
3797
3798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3799
3800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3801 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3802 .build());
3803
3804 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3805
3806 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3807 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3808 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3809
3810 // After the device has been reset, a new hovering stream can be sent to the window
3811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3812 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3813 .build());
3814 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3815}
3816
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003817TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003819 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3820 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003821 window->setFocusable(true);
3822
3823 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3824 setFocusedWindow(window);
3825
3826 window->consumeFocusEvent(true);
3827
Prabir Pradhan678438e2023-04-13 19:32:51 +00003828 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003829 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3830 const nsecs_t injectTime = keyArgs.eventTime;
3831 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003832 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003833 // The dispatching time should be always greater than or equal to intercept key timeout.
3834 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3835 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3836 std::chrono::nanoseconds(interceptKeyTimeout).count());
3837}
3838
3839TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003841 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3842 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003843 window->setFocusable(true);
3844
3845 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3846 setFocusedWindow(window);
3847
3848 window->consumeFocusEvent(true);
3849
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003850 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003851 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3852 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003853
3854 // Window should receive key event immediately when same key up.
3855 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3856 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3857}
3858
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003859/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003860 * Two windows. First is a regular window. Second does not overlap with the first, and has
3861 * WATCH_OUTSIDE_TOUCH.
3862 * Both windows are owned by the same UID.
3863 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3864 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3865 */
3866TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3867 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3868 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3869 "First Window", ADISPLAY_ID_DEFAULT);
3870 window->setFrame(Rect{0, 0, 100, 100});
3871
3872 sp<FakeWindowHandle> outsideWindow =
3873 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3874 ADISPLAY_ID_DEFAULT);
3875 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3876 outsideWindow->setWatchOutsideTouch(true);
3877 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3879
3880 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003881 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3882 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3883 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003884 window->consumeMotionDown();
3885 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3886 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3887 outsideWindow->consumeMotionEvent(
3888 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3889}
3890
3891/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003892 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3893 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3894 * ACTION_OUTSIDE event is sent per gesture.
3895 */
3896TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3897 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003899 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3900 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003901 window->setWatchOutsideTouch(true);
3902 window->setFrame(Rect{0, 0, 100, 100});
3903 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003904 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3905 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003906 secondWindow->setFrame(Rect{100, 100, 200, 200});
3907 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003908 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3909 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003910 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3912
3913 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003914 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3915 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3916 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003917 window->assertNoEvents();
3918 secondWindow->assertNoEvents();
3919
3920 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3921 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003922 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3923 ADISPLAY_ID_DEFAULT,
3924 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003925 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3926 window->consumeMotionEvent(
3927 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003928 secondWindow->consumeMotionDown();
3929 thirdWindow->assertNoEvents();
3930
3931 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3932 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003933 mDispatcher->notifyMotion(
3934 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3935 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003936 window->assertNoEvents();
3937 secondWindow->consumeMotionMove();
3938 thirdWindow->consumeMotionDown();
3939}
3940
Prabir Pradhan814fe082022-07-22 20:22:18 +00003941TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003943 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3944 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003945 window->setFocusable(true);
3946
Patrick Williamsd828f302023-04-28 17:52:08 -05003947 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003948 setFocusedWindow(window);
3949
3950 window->consumeFocusEvent(true);
3951
Prabir Pradhan678438e2023-04-13 19:32:51 +00003952 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3953 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3954 mDispatcher->notifyKey(keyDown);
3955 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003956
3957 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3958 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3959
3960 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003961 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003962
3963 window->consumeFocusEvent(false);
3964
Prabir Pradhan678438e2023-04-13 19:32:51 +00003965 mDispatcher->notifyKey(keyDown);
3966 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003967 window->assertNoEvents();
3968}
3969
Arthur Hung96483742022-11-15 03:30:48 +00003970TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3972 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3973 "Fake Window", ADISPLAY_ID_DEFAULT);
3974 // Ensure window is non-split and have some transform.
3975 window->setPreventSplitting(true);
3976 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003977 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003978
3979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3980 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3981 {50, 50}))
3982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3983 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3984
3985 const MotionEvent secondFingerDownEvent =
3986 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3987 .displayId(ADISPLAY_ID_DEFAULT)
3988 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003989 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3990 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003991 .build();
3992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3993 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3994 InputEventInjectionSync::WAIT_FOR_RESULT))
3995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3996
3997 const MotionEvent* event = window->consumeMotion();
3998 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3999 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4000 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4001 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4002 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
4003}
4004
Harry Cuttsb166c002023-05-09 13:06:05 +00004005TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4006 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4007 sp<FakeWindowHandle> window =
4008 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4009 window->setFrame(Rect(0, 0, 400, 400));
4010 sp<FakeWindowHandle> trustedOverlay =
4011 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4012 ADISPLAY_ID_DEFAULT);
4013 trustedOverlay->setSpy(true);
4014 trustedOverlay->setTrustedOverlay(true);
4015
4016 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
4017
4018 // Start a three-finger touchpad swipe
4019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4020 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4021 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4022 .build());
4023 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4024 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4025 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4026 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4027 .build());
4028 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4029 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4030 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4031 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4032 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4033 .build());
4034
4035 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4036 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4037 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4038
4039 // Move the swipe a bit
4040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4041 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4042 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4043 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4044 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4045 .build());
4046
4047 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4048
4049 // End the swipe
4050 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4051 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4052 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4053 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4054 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4055 .build());
4056 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4057 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4058 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4059 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4060 .build());
4061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4062 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4063 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4064 .build());
4065
4066 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4067 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4068 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4069
4070 window->assertNoEvents();
4071}
4072
4073TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4075 sp<FakeWindowHandle> window =
4076 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4077 window->setFrame(Rect(0, 0, 400, 400));
4078 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4079
4080 // Start a three-finger touchpad swipe
4081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4082 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4083 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4084 .build());
4085 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4086 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4087 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4088 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4089 .build());
4090 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4091 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4092 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4093 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4094 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4095 .build());
4096
4097 // Move the swipe a bit
4098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4099 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4100 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4101 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4102 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4103 .build());
4104
4105 // End the swipe
4106 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4107 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4108 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4109 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4110 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4111 .build());
4112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4113 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4114 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4115 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4116 .build());
4117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4118 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4119 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4120 .build());
4121
4122 window->assertNoEvents();
4123}
4124
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004125/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004126 * Ensure the correct coordinate spaces are used by InputDispatcher.
4127 *
4128 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4129 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4130 * space.
4131 */
4132class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4133public:
4134 void SetUp() override {
4135 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004136 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004137 }
4138
4139 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4140 gui::DisplayInfo info;
4141 info.displayId = displayId;
4142 info.transform = transform;
4143 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004144 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004145 }
4146
4147 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4148 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004149 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004150 }
4151
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004152 void removeAllWindowsAndDisplays() {
4153 mDisplayInfos.clear();
4154 mWindowInfos.clear();
4155 }
4156
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004157 // Set up a test scenario where the display has a scaled projection and there are two windows
4158 // on the display.
4159 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4160 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4161 // respectively.
4162 ui::Transform displayTransform;
4163 displayTransform.set(2, 0, 0, 4);
4164 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4165
4166 std::shared_ptr<FakeApplicationHandle> application =
4167 std::make_shared<FakeApplicationHandle>();
4168
4169 // Add two windows to the display. Their frames are represented in the display space.
4170 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004171 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4172 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004173 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4174 addWindow(firstWindow);
4175
4176 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004177 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4178 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004179 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4180 addWindow(secondWindow);
4181 return {std::move(firstWindow), std::move(secondWindow)};
4182 }
4183
4184private:
4185 std::vector<gui::DisplayInfo> mDisplayInfos;
4186 std::vector<gui::WindowInfo> mWindowInfos;
4187};
4188
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004189TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004190 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4191 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004192 // selected so that if the hit test was performed with the point and the bounds being in
4193 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004194 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4195 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4196 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004197
4198 firstWindow->consumeMotionDown();
4199 secondWindow->assertNoEvents();
4200}
4201
4202// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4203// the event should be treated as being in the logical display space.
4204TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4205 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4206 // Send down to the first window. The point is represented in the logical display space. The
4207 // point is selected so that if the hit test was done in logical display space, then it would
4208 // end up in the incorrect window.
4209 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4210 PointF{75 * 2, 55 * 4});
4211
4212 firstWindow->consumeMotionDown();
4213 secondWindow->assertNoEvents();
4214}
4215
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004216// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4217// event should be treated as being in the logical display space.
4218TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4219 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4220
4221 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4222 ui::Transform injectedEventTransform;
4223 injectedEventTransform.set(matrix);
4224 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4225 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4226
4227 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4228 .displayId(ADISPLAY_ID_DEFAULT)
4229 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004230 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004231 .x(untransformedPoint.x)
4232 .y(untransformedPoint.y))
4233 .build();
4234 event.transform(matrix);
4235
4236 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4237 InputEventInjectionSync::WAIT_FOR_RESULT);
4238
4239 firstWindow->consumeMotionDown();
4240 secondWindow->assertNoEvents();
4241}
4242
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004243TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4244 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4245
4246 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004247 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4248 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4249 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004250
4251 firstWindow->assertNoEvents();
4252 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004253 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004254 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4255
4256 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4257 EXPECT_EQ(300, event->getRawX(0));
4258 EXPECT_EQ(880, event->getRawY(0));
4259
4260 // Ensure that the x and y values are in the window's coordinate space.
4261 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4262 // the logical display space. This will be the origin of the window space.
4263 EXPECT_EQ(100, event->getX(0));
4264 EXPECT_EQ(80, event->getY(0));
4265}
4266
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004267/** Ensure consistent behavior of InputDispatcher in all orientations. */
4268class InputDispatcherDisplayOrientationFixture
4269 : public InputDispatcherDisplayProjectionTest,
4270 public ::testing::WithParamInterface<ui::Rotation> {};
4271
4272// This test verifies the touchable region of a window for all rotations of the display by tapping
4273// in different locations on the display, specifically points close to the four corners of a
4274// window.
4275TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4276 constexpr static int32_t displayWidth = 400;
4277 constexpr static int32_t displayHeight = 800;
4278
4279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4280
4281 const auto rotation = GetParam();
4282
4283 // Set up the display with the specified rotation.
4284 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4285 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4286 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4287 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4288 logicalDisplayWidth, logicalDisplayHeight);
4289 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4290
4291 // Create a window with its bounds determined in the logical display.
4292 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4293 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4294 sp<FakeWindowHandle> window =
4295 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4296 window->setFrame(frameInDisplay, displayTransform);
4297 addWindow(window);
4298
4299 // The following points in logical display space should be inside the window.
4300 static const std::array<vec2, 4> insidePoints{
4301 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4302 for (const auto pointInsideWindow : insidePoints) {
4303 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4304 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004305 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4306 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4307 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004308 window->consumeMotionDown();
4309
Prabir Pradhan678438e2023-04-13 19:32:51 +00004310 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4311 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4312 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004313 window->consumeMotionUp();
4314 }
4315
4316 // The following points in logical display space should be outside the window.
4317 static const std::array<vec2, 5> outsidePoints{
4318 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4319 for (const auto pointOutsideWindow : outsidePoints) {
4320 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4321 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004322 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4323 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4324 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004325
Prabir Pradhan678438e2023-04-13 19:32:51 +00004326 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4327 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4328 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004329 }
4330 window->assertNoEvents();
4331}
4332
4333// Run the precision tests for all rotations.
4334INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4335 InputDispatcherDisplayOrientationFixture,
4336 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4337 ui::ROTATION_270),
4338 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4339 return ftl::enum_string(testParamInfo.param);
4340 });
4341
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004342using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4343 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004344
4345class TransferTouchFixture : public InputDispatcherTest,
4346 public ::testing::WithParamInterface<TransferFunction> {};
4347
4348TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004350
4351 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004352 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004353 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4354 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004355 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004356 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004357 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4358 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004359 sp<FakeWindowHandle> wallpaper =
4360 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4361 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004362 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004363 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004364
4365 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004366 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4367 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004368
Svet Ganov5d3bc372020-01-26 23:11:07 -08004369 // Only the first window should get the down event
4370 firstWindow->consumeMotionDown();
4371 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004372 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004373
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004374 // Transfer touch to the second window
4375 TransferFunction f = GetParam();
4376 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4377 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004378 // The first window gets cancel and the second gets down
4379 firstWindow->consumeMotionCancel();
4380 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004381 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004382
4383 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4385 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004386 // The first window gets no events and the second gets up
4387 firstWindow->assertNoEvents();
4388 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004389 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004390}
4391
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004392/**
4393 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4394 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4395 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4396 * natural to the user.
4397 * In this test, we are sending a pointer to both spy window and first window. We then try to
4398 * transfer touch to the second window. The dispatcher should identify the first window as the
4399 * one that should lose the gesture, and therefore the action should be to move the gesture from
4400 * the first window to the second.
4401 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4402 * the other API, as well.
4403 */
4404TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4406
4407 // Create a couple of windows + a spy window
4408 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004409 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004410 spyWindow->setTrustedOverlay(true);
4411 spyWindow->setSpy(true);
4412 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004413 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004414 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004415 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004416
4417 // Add the windows to the dispatcher
4418 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4419
4420 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004421 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4422 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004423 // Only the first window and spy should get the down event
4424 spyWindow->consumeMotionDown();
4425 firstWindow->consumeMotionDown();
4426
4427 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4428 // if f === 'transferTouch'.
4429 TransferFunction f = GetParam();
4430 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4431 ASSERT_TRUE(success);
4432 // The first window gets cancel and the second gets down
4433 firstWindow->consumeMotionCancel();
4434 secondWindow->consumeMotionDown();
4435
4436 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004437 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4438 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004439 // The first window gets no events and the second+spy get up
4440 firstWindow->assertNoEvents();
4441 spyWindow->consumeMotionUp();
4442 secondWindow->consumeMotionUp();
4443}
4444
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004445TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004447
4448 PointF touchPoint = {10, 10};
4449
4450 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004451 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004452 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4453 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004454 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004455 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004456 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4457 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004458 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459
4460 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004462
4463 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4465 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4466 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004467 // Only the first window should get the down event
4468 firstWindow->consumeMotionDown();
4469 secondWindow->assertNoEvents();
4470
4471 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004472 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4473 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004474 // Only the first window should get the pointer down event
4475 firstWindow->consumeMotionPointerDown(1);
4476 secondWindow->assertNoEvents();
4477
4478 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004479 TransferFunction f = GetParam();
4480 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4481 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004482 // The first window gets cancel and the second gets down and pointer down
4483 firstWindow->consumeMotionCancel();
4484 secondWindow->consumeMotionDown();
4485 secondWindow->consumeMotionPointerDown(1);
4486
4487 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4489 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004490 // The first window gets nothing and the second gets pointer up
4491 firstWindow->assertNoEvents();
4492 secondWindow->consumeMotionPointerUp(1);
4493
4494 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004495 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4496 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004497 // The first window gets nothing and the second gets up
4498 firstWindow->assertNoEvents();
4499 secondWindow->consumeMotionUp();
4500}
4501
Arthur Hungc539dbb2022-12-08 07:45:36 +00004502TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4504
4505 // Create a couple of windows
4506 sp<FakeWindowHandle> firstWindow =
4507 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4508 ADISPLAY_ID_DEFAULT);
4509 firstWindow->setDupTouchToWallpaper(true);
4510 sp<FakeWindowHandle> secondWindow =
4511 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4512 ADISPLAY_ID_DEFAULT);
4513 secondWindow->setDupTouchToWallpaper(true);
4514
4515 sp<FakeWindowHandle> wallpaper1 =
4516 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4517 wallpaper1->setIsWallpaper(true);
4518
4519 sp<FakeWindowHandle> wallpaper2 =
4520 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4521 wallpaper2->setIsWallpaper(true);
4522 // Add the windows to the dispatcher
4523 mDispatcher->setInputWindows(
4524 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4525
4526 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004527 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4528 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004529
4530 // Only the first window should get the down event
4531 firstWindow->consumeMotionDown();
4532 secondWindow->assertNoEvents();
4533 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4534 wallpaper2->assertNoEvents();
4535
4536 // Transfer touch focus to the second window
4537 TransferFunction f = GetParam();
4538 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4539 ASSERT_TRUE(success);
4540
4541 // The first window gets cancel and the second gets down
4542 firstWindow->consumeMotionCancel();
4543 secondWindow->consumeMotionDown();
4544 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4545 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4546
4547 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004548 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4549 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004550 // The first window gets no events and the second gets up
4551 firstWindow->assertNoEvents();
4552 secondWindow->consumeMotionUp();
4553 wallpaper1->assertNoEvents();
4554 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4555}
4556
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004557// For the cases of single pointer touch and two pointers non-split touch, the api's
4558// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4559// for the case where there are multiple pointers split across several windows.
4560INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4561 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004562 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4563 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004564 return dispatcher->transferTouch(destChannelToken,
4565 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004566 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004567 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4568 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004569 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004570 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004571 }));
4572
Svet Ganov5d3bc372020-01-26 23:11:07 -08004573TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004574 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004575
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004576 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004577 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4578 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004579 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004580
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004581 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004582 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4583 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004584 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004585
4586 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004588
4589 PointF pointInFirst = {300, 200};
4590 PointF pointInSecond = {300, 600};
4591
4592 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4594 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4595 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004596 // Only the first window should get the down event
4597 firstWindow->consumeMotionDown();
4598 secondWindow->assertNoEvents();
4599
4600 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004601 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4602 ADISPLAY_ID_DEFAULT,
4603 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004604 // The first window gets a move and the second a down
4605 firstWindow->consumeMotionMove();
4606 secondWindow->consumeMotionDown();
4607
4608 // Transfer touch focus to the second window
4609 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4610 // The first window gets cancel and the new gets pointer down (it already saw down)
4611 firstWindow->consumeMotionCancel();
4612 secondWindow->consumeMotionPointerDown(1);
4613
4614 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004615 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4616 ADISPLAY_ID_DEFAULT,
4617 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004618 // The first window gets nothing and the second gets pointer up
4619 firstWindow->assertNoEvents();
4620 secondWindow->consumeMotionPointerUp(1);
4621
4622 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004623 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4624 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004625 // The first window gets nothing and the second gets up
4626 firstWindow->assertNoEvents();
4627 secondWindow->consumeMotionUp();
4628}
4629
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004630// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4631// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4632// touch is not supported, so the touch should continue on those windows and the transferred-to
4633// window should get nothing.
4634TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4635 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4636
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004637 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004638 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4639 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004640 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004641
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004642 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004643 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4644 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004645 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004646
4647 // Add the windows to the dispatcher
4648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4649
4650 PointF pointInFirst = {300, 200};
4651 PointF pointInSecond = {300, 600};
4652
4653 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004654 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4655 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4656 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004657 // Only the first window should get the down event
4658 firstWindow->consumeMotionDown();
4659 secondWindow->assertNoEvents();
4660
4661 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004662 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4663 ADISPLAY_ID_DEFAULT,
4664 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004665 // The first window gets a move and the second a down
4666 firstWindow->consumeMotionMove();
4667 secondWindow->consumeMotionDown();
4668
4669 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004670 const bool transferred =
4671 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004672 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4673 ASSERT_FALSE(transferred);
4674 firstWindow->assertNoEvents();
4675 secondWindow->assertNoEvents();
4676
4677 // The rest of the dispatch should proceed as normal
4678 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004679 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4680 ADISPLAY_ID_DEFAULT,
4681 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004682 // The first window gets MOVE and the second gets pointer up
4683 firstWindow->consumeMotionMove();
4684 secondWindow->consumeMotionUp();
4685
4686 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4688 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004689 // The first window gets nothing and the second gets up
4690 firstWindow->consumeMotionUp();
4691 secondWindow->assertNoEvents();
4692}
4693
Arthur Hungabbb9d82021-09-01 14:52:30 +00004694// This case will create two windows and one mirrored window on the default display and mirror
4695// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4696// the windows info of second display before default display.
4697TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4699 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004700 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004701 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004702 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004703 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004704 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004705
4706 sp<FakeWindowHandle> mirrorWindowInPrimary =
4707 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4708 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004709
4710 sp<FakeWindowHandle> firstWindowInSecondary =
4711 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4712 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004713
4714 sp<FakeWindowHandle> secondWindowInSecondary =
4715 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4716 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004717
4718 // Update window info, let it find window handle of second display first.
4719 mDispatcher->setInputWindows(
4720 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4721 {ADISPLAY_ID_DEFAULT,
4722 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4723
4724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4725 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4726 {50, 50}))
4727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4728
4729 // Window should receive motion event.
4730 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4731
4732 // Transfer touch focus
4733 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4734 secondWindowInPrimary->getToken()));
4735 // The first window gets cancel.
4736 firstWindowInPrimary->consumeMotionCancel();
4737 secondWindowInPrimary->consumeMotionDown();
4738
4739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4740 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4741 ADISPLAY_ID_DEFAULT, {150, 50}))
4742 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4743 firstWindowInPrimary->assertNoEvents();
4744 secondWindowInPrimary->consumeMotionMove();
4745
4746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4747 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4748 {150, 50}))
4749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4750 firstWindowInPrimary->assertNoEvents();
4751 secondWindowInPrimary->consumeMotionUp();
4752}
4753
4754// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4755// 'transferTouch' api.
4756TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4758 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004759 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004760 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004761 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004762 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004763 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004764
4765 sp<FakeWindowHandle> mirrorWindowInPrimary =
4766 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4767 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004768
4769 sp<FakeWindowHandle> firstWindowInSecondary =
4770 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4771 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004772
4773 sp<FakeWindowHandle> secondWindowInSecondary =
4774 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4775 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004776
4777 // Update window info, let it find window handle of second display first.
4778 mDispatcher->setInputWindows(
4779 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4780 {ADISPLAY_ID_DEFAULT,
4781 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4782
4783 // Touch on second display.
4784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4785 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4787
4788 // Window should receive motion event.
4789 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4790
4791 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004792 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004793
4794 // The first window gets cancel.
4795 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4796 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4797
4798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4799 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4800 SECOND_DISPLAY_ID, {150, 50}))
4801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4802 firstWindowInPrimary->assertNoEvents();
4803 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4804
4805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4806 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4807 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4808 firstWindowInPrimary->assertNoEvents();
4809 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4810}
4811
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004812TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004813 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004814 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4815 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004816
Vishnu Nair47074b82020-08-14 11:54:47 -07004817 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004819 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004820
4821 window->consumeFocusEvent(true);
4822
Prabir Pradhan678438e2023-04-13 19:32:51 +00004823 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004824
4825 // Window should receive key down event.
4826 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004827
4828 // Should have poked user activity
4829 mFakePolicy->assertUserActivityPoked();
4830}
4831
4832TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4833 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4834 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4835 "Fake Window", ADISPLAY_ID_DEFAULT);
4836
4837 window->setDisableUserActivity(true);
4838 window->setFocusable(true);
4839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4840 setFocusedWindow(window);
4841
4842 window->consumeFocusEvent(true);
4843
4844 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4845
4846 // Window should receive key down event.
4847 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4848
4849 // Should have poked user activity
4850 mFakePolicy->assertUserActivityNotPoked();
4851}
4852
4853TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4855 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4856 "Fake Window", ADISPLAY_ID_DEFAULT);
4857
4858 window->setFocusable(true);
4859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4860 setFocusedWindow(window);
4861
4862 window->consumeFocusEvent(true);
4863
4864 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4865 mDispatcher->waitForIdle();
4866
4867 // System key is not passed down
4868 window->assertNoEvents();
4869
4870 // Should have poked user activity
4871 mFakePolicy->assertUserActivityPoked();
4872}
4873
4874TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4876 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4877 "Fake Window", ADISPLAY_ID_DEFAULT);
4878
4879 window->setFocusable(true);
4880 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4881 setFocusedWindow(window);
4882
4883 window->consumeFocusEvent(true);
4884
4885 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4886 mDispatcher->waitForIdle();
4887
4888 // System key is not passed down
4889 window->assertNoEvents();
4890
4891 // Should have poked user activity
4892 mFakePolicy->assertUserActivityPoked();
4893}
4894
4895TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4896 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4897 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4898 "Fake Window", ADISPLAY_ID_DEFAULT);
4899
4900 window->setDisableUserActivity(true);
4901 window->setFocusable(true);
4902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4903 setFocusedWindow(window);
4904
4905 window->consumeFocusEvent(true);
4906
4907 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4908 mDispatcher->waitForIdle();
4909
4910 // System key is not passed down
4911 window->assertNoEvents();
4912
4913 // Should have poked user activity
4914 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004915}
4916
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004917TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4919 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4920 "Fake Window", ADISPLAY_ID_DEFAULT);
4921
4922 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4923
4924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4925 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4926 ADISPLAY_ID_DEFAULT, {100, 100}))
4927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4928
4929 window->consumeMotionEvent(
4930 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4931
4932 // Should have poked user activity
4933 mFakePolicy->assertUserActivityPoked();
4934}
4935
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004936TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4939 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004940
Arthur Hung72d8dc32020-03-28 00:48:39 +00004941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004942
Prabir Pradhan678438e2023-04-13 19:32:51 +00004943 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004944 mDispatcher->waitForIdle();
4945
4946 window->assertNoEvents();
4947}
4948
4949// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4950TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004952 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4953 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004954
Arthur Hung72d8dc32020-03-28 00:48:39 +00004955 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004956
4957 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004958 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004959 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004960 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4961 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004962
4963 // Window should receive only the motion event
4964 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4965 window->assertNoEvents(); // Key event or focus event will not be received
4966}
4967
arthurhungea3f4fc2020-12-21 23:18:53 +08004968TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4970
arthurhungea3f4fc2020-12-21 23:18:53 +08004971 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004972 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4973 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004974 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004975
arthurhungea3f4fc2020-12-21 23:18:53 +08004976 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004977 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4978 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004979 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004980
4981 // Add the windows to the dispatcher
4982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4983
4984 PointF pointInFirst = {300, 200};
4985 PointF pointInSecond = {300, 600};
4986
4987 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004988 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4989 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4990 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004991 // Only the first window should get the down event
4992 firstWindow->consumeMotionDown();
4993 secondWindow->assertNoEvents();
4994
4995 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004996 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4997 ADISPLAY_ID_DEFAULT,
4998 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004999 // The first window gets a move and the second a down
5000 firstWindow->consumeMotionMove();
5001 secondWindow->consumeMotionDown();
5002
5003 // Send pointer cancel to the second window
5004 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005005 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005006 {pointInFirst, pointInSecond});
5007 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005008 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005009 // The first window gets move and the second gets cancel.
5010 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5011 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5012
5013 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005014 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5015 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005016 // The first window gets up and the second gets nothing.
5017 firstWindow->consumeMotionUp();
5018 secondWindow->assertNoEvents();
5019}
5020
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005021TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5023
5024 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005025 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5027 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5028 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5029 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5030
Harry Cutts33476232023-01-30 19:57:29 +00005031 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005032 window->assertNoEvents();
5033 mDispatcher->waitForIdle();
5034}
5035
chaviwd1c23182019-12-20 18:44:56 -08005036class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00005037public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005038 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005039 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07005040 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08005041 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07005042 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00005043 }
5044
chaviwd1c23182019-12-20 18:44:56 -08005045 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
5046
5047 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005048 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
5049 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08005050 }
5051
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005052 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
5053
5054 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5055
chaviwd1c23182019-12-20 18:44:56 -08005056 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005057 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005058 expectedDisplayId, expectedFlags);
5059 }
5060
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005061 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005062 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005063 expectedDisplayId, expectedFlags);
5064 }
5065
chaviwd1c23182019-12-20 18:44:56 -08005066 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005067 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005068 expectedDisplayId, expectedFlags);
5069 }
5070
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005071 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005072 mInputReceiver->consumeMotionEvent(
5073 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5074 WithDisplayId(expectedDisplayId),
5075 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005076 }
5077
Arthur Hungfbfa5722021-11-16 02:45:54 +00005078 void consumeMotionPointerDown(int32_t pointerIdx) {
5079 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5080 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005081 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005082 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005083 }
5084
Evan Rosky84f07f02021-04-16 10:42:42 -07005085 MotionEvent* consumeMotion() {
5086 InputEvent* event = mInputReceiver->consume();
5087 if (!event) {
5088 ADD_FAILURE() << "No event was produced";
5089 return nullptr;
5090 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005091 if (event->getType() != InputEventType::MOTION) {
5092 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07005093 return nullptr;
5094 }
5095 return static_cast<MotionEvent*>(event);
5096 }
5097
chaviwd1c23182019-12-20 18:44:56 -08005098 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5099
5100private:
5101 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005102};
5103
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005104using InputDispatcherMonitorTest = InputDispatcherTest;
5105
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005106/**
5107 * Two entities that receive touch: A window, and a global monitor.
5108 * The touch goes to the window, and then the window disappears.
5109 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5110 * for the monitor, as well.
5111 * 1. foregroundWindow
5112 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5113 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005114TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5116 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005117 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005118
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005119 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005120
5121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5123 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5124 {100, 200}))
5125 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5126
5127 // Both the foreground window and the global monitor should receive the touch down
5128 window->consumeMotionDown();
5129 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5130
5131 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5132 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5133 ADISPLAY_ID_DEFAULT, {110, 200}))
5134 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5135
5136 window->consumeMotionMove();
5137 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5138
5139 // Now the foreground window goes away
5140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5141 window->consumeMotionCancel();
5142 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5143
5144 // If more events come in, there will be no more foreground window to send them to. This will
5145 // cause a cancel for the monitor, as well.
5146 ASSERT_EQ(InputEventInjectionResult::FAILED,
5147 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5148 ADISPLAY_ID_DEFAULT, {120, 200}))
5149 << "Injection should fail because the window was removed";
5150 window->assertNoEvents();
5151 // Global monitor now gets the cancel
5152 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5153}
5154
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005155TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005157 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5158 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005160
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005161 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005162
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005164 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005166 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005167 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005168}
5169
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005170TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5171 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005172
Chris Yea209fde2020-07-22 13:54:51 -07005173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5175 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005176 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005177
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005178 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005179 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005180 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005181 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005182 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005183
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005184 // Pilfer pointers from the monitor.
5185 // This should not do anything and the window should continue to receive events.
5186 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005187
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005189 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5190 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005191 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005192
5193 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5194 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005195}
5196
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005197TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005199 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5200 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5202 window->setWindowOffset(20, 40);
5203 window->setWindowTransform(0, 1, -1, 0);
5204
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005205 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005206
5207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5208 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5209 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5210 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5211 MotionEvent* event = monitor.consumeMotion();
5212 // Even though window has transform, gesture monitor must not.
5213 ASSERT_EQ(ui::Transform(), event->getTransform());
5214}
5215
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005216TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005217 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005218 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005219
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005220 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005221 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005222 << "Injection should fail if there is a monitor, but no touchable window";
5223 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005224}
5225
chaviw81e2bb92019-12-18 15:03:51 -08005226TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005227 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005228 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5229 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005230
Arthur Hung72d8dc32020-03-28 00:48:39 +00005231 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005232
5233 NotifyMotionArgs motionArgs =
5234 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5235 ADISPLAY_ID_DEFAULT);
5236
Prabir Pradhan678438e2023-04-13 19:32:51 +00005237 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005238 // Window should receive motion down event.
5239 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5240
5241 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005242 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005243 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5244 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5245 motionArgs.pointerCoords[0].getX() - 10);
5246
Prabir Pradhan678438e2023-04-13 19:32:51 +00005247 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005248 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005249 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005250}
5251
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005252/**
5253 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5254 * the device default right away. In the test scenario, we check both the default value,
5255 * and the action of enabling / disabling.
5256 */
5257TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005259 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5260 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005261 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005262
5263 // Set focused application.
5264 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005265 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005266
5267 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005268 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005269 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005270 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005271
5272 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005273 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005275 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005276
5277 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005278 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005279 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005280 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005281 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005283 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005284 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005285
5286 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005287 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005289 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005290
5291 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005292 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005293 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005294 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005295 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005297 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005298 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005299
5300 window->assertNoEvents();
5301}
5302
Gang Wange9087892020-01-07 12:17:14 -05005303TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005305 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5306 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005307
5308 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005309 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005310
Arthur Hung72d8dc32020-03-28 00:48:39 +00005311 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005312 setFocusedWindow(window);
5313
Harry Cutts33476232023-01-30 19:57:29 +00005314 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005315
Prabir Pradhan678438e2023-04-13 19:32:51 +00005316 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5317 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005318
5319 InputEvent* event = window->consume();
5320 ASSERT_NE(event, nullptr);
5321
5322 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5323 ASSERT_NE(verified, nullptr);
5324 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5325
5326 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5327 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5328 ASSERT_EQ(keyArgs.source, verified->source);
5329 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5330
5331 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5332
5333 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005334 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005335 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005336 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5337 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5338 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5339 ASSERT_EQ(0, verifiedKey.repeatCount);
5340}
5341
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005342TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005344 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5345 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005346
5347 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5348
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005349 ui::Transform transform;
5350 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5351
5352 gui::DisplayInfo displayInfo;
5353 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5354 displayInfo.transform = transform;
5355
Patrick Williamsd828f302023-04-28 17:52:08 -05005356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005357
Prabir Pradhan678438e2023-04-13 19:32:51 +00005358 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005359 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5360 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005361 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005362
5363 InputEvent* event = window->consume();
5364 ASSERT_NE(event, nullptr);
5365
5366 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5367 ASSERT_NE(verified, nullptr);
5368 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5369
5370 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5371 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5372 EXPECT_EQ(motionArgs.source, verified->source);
5373 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5374
5375 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5376
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005377 const vec2 rawXY =
5378 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5379 motionArgs.pointerCoords[0].getXYValue());
5380 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5381 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005382 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005383 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005384 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005385 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5386 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5387}
5388
chaviw09c8d2d2020-08-24 15:48:26 -07005389/**
5390 * Ensure that separate calls to sign the same data are generating the same key.
5391 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5392 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5393 * tests.
5394 */
5395TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5396 KeyEvent event = getTestKeyEvent();
5397 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5398
5399 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5400 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5401 ASSERT_EQ(hmac1, hmac2);
5402}
5403
5404/**
5405 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5406 */
5407TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5408 KeyEvent event = getTestKeyEvent();
5409 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5410 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5411
5412 verifiedEvent.deviceId += 1;
5413 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5414
5415 verifiedEvent.source += 1;
5416 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5417
5418 verifiedEvent.eventTimeNanos += 1;
5419 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5420
5421 verifiedEvent.displayId += 1;
5422 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5423
5424 verifiedEvent.action += 1;
5425 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5426
5427 verifiedEvent.downTimeNanos += 1;
5428 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5429
5430 verifiedEvent.flags += 1;
5431 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5432
5433 verifiedEvent.keyCode += 1;
5434 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5435
5436 verifiedEvent.scanCode += 1;
5437 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5438
5439 verifiedEvent.metaState += 1;
5440 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5441
5442 verifiedEvent.repeatCount += 1;
5443 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5444}
5445
Vishnu Nair958da932020-08-21 17:12:37 -07005446TEST_F(InputDispatcherTest, SetFocusedWindow) {
5447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5448 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005449 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005450 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005451 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005452 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5453
5454 // Top window is also focusable but is not granted focus.
5455 windowTop->setFocusable(true);
5456 windowSecond->setFocusable(true);
5457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5458 setFocusedWindow(windowSecond);
5459
5460 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5462 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005463
5464 // Focused window should receive event.
5465 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5466 windowTop->assertNoEvents();
5467}
5468
5469TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5471 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005472 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005473 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5474
5475 window->setFocusable(true);
5476 // Release channel for window is no longer valid.
5477 window->releaseChannel();
5478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5479 setFocusedWindow(window);
5480
5481 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005482 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5483 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005484
5485 // window channel is invalid, so it should not receive any input event.
5486 window->assertNoEvents();
5487}
5488
5489TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5491 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005493 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005494 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5495
Vishnu Nair958da932020-08-21 17:12:37 -07005496 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5497 setFocusedWindow(window);
5498
5499 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005500 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5501 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005502
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005503 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005504 window->assertNoEvents();
5505}
5506
5507TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5509 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005510 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005511 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005512 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005513 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5514
5515 windowTop->setFocusable(true);
5516 windowSecond->setFocusable(true);
5517 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5518 setFocusedWindow(windowTop);
5519 windowTop->consumeFocusEvent(true);
5520
Chavi Weingarten847e8512023-03-29 00:26:09 +00005521 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5522 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005523 windowSecond->consumeFocusEvent(true);
5524 windowTop->consumeFocusEvent(false);
5525
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5527 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005528
5529 // Focused window should receive event.
5530 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5531}
5532
Chavi Weingarten847e8512023-03-29 00:26:09 +00005533TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5535 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005536 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005537 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005538 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005539 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5540
5541 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005542 windowSecond->setFocusable(false);
5543 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005544 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005545 setFocusedWindow(windowTop);
5546 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005547
Chavi Weingarten847e8512023-03-29 00:26:09 +00005548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5549 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005550
5551 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005552 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005553 windowSecond->assertNoEvents();
5554}
5555
5556TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5558 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005559 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005560 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005561 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5562 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005563 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5564
5565 window->setFocusable(true);
5566 previousFocusedWindow->setFocusable(true);
5567 window->setVisible(false);
5568 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5569 setFocusedWindow(previousFocusedWindow);
5570 previousFocusedWindow->consumeFocusEvent(true);
5571
5572 // Requesting focus on invisible window takes focus from currently focused window.
5573 setFocusedWindow(window);
5574 previousFocusedWindow->consumeFocusEvent(false);
5575
5576 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005578 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5579 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005580
5581 // Window does not get focus event or key down.
5582 window->assertNoEvents();
5583
5584 // Window becomes visible.
5585 window->setVisible(true);
5586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5587
5588 // Window receives focus event.
5589 window->consumeFocusEvent(true);
5590 // Focused window receives key down.
5591 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5592}
5593
Vishnu Nair599f1412021-06-21 10:39:58 -07005594TEST_F(InputDispatcherTest, DisplayRemoved) {
5595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5596 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005597 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005598 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5599
5600 // window is granted focus.
5601 window->setFocusable(true);
5602 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5603 setFocusedWindow(window);
5604 window->consumeFocusEvent(true);
5605
5606 // When a display is removed window loses focus.
5607 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5608 window->consumeFocusEvent(false);
5609}
5610
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005611/**
5612 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5613 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5614 * of the 'slipperyEnterWindow'.
5615 *
5616 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5617 * a way so that the touched location is no longer covered by the top window.
5618 *
5619 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5620 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5621 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5622 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5623 * with ACTION_DOWN).
5624 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5625 * window moved itself away from the touched location and had Flag::SLIPPERY.
5626 *
5627 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5628 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5629 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5630 *
5631 * In this test, we ensure that the event received by the bottom window has
5632 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5633 */
5634TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005635 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5636 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005637
5638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5639 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5640
5641 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005642 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005643 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005644 // Make sure this one overlaps the bottom window
5645 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5646 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5647 // one. Windows with the same owner are not considered to be occluding each other.
5648 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5649
5650 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005651 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005652 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5653
5654 mDispatcher->setInputWindows(
5655 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5656
5657 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005658 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5659 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5660 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005661 slipperyExitWindow->consumeMotionDown();
5662 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5663 mDispatcher->setInputWindows(
5664 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5665
Prabir Pradhan678438e2023-04-13 19:32:51 +00005666 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5667 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5668 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005669
5670 slipperyExitWindow->consumeMotionCancel();
5671
5672 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5673 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5674}
5675
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005676/**
5677 * Two windows, one on the left and another on the right. The left window is slippery. The right
5678 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5679 * touch moves from the left window into the right window, the gesture should continue to go to the
5680 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5681 * reproduces a crash.
5682 */
5683TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5685
5686 sp<FakeWindowHandle> leftSlipperyWindow =
5687 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5688 leftSlipperyWindow->setSlippery(true);
5689 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5690
5691 sp<FakeWindowHandle> rightDropTouchesWindow =
5692 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5693 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5694 rightDropTouchesWindow->setDropInput(true);
5695
5696 mDispatcher->setInputWindows(
5697 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5698
5699 // Start touch in the left window
5700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5701 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5702 .build());
5703 leftSlipperyWindow->consumeMotionDown();
5704
5705 // And move it into the right window
5706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5707 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5708 .build());
5709
5710 // Since the right window isn't eligible to receive input, touch does not slip.
5711 // The left window continues to receive the gesture.
5712 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5713 rightDropTouchesWindow->assertNoEvents();
5714}
5715
Garfield Tan1c7bc862020-01-28 13:24:04 -08005716class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5717protected:
5718 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5719 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5720
Chris Yea209fde2020-07-22 13:54:51 -07005721 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005722 sp<FakeWindowHandle> mWindow;
5723
5724 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005725 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005726 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005727 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005728 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005729 ASSERT_EQ(OK, mDispatcher->start());
5730
5731 setUpWindow();
5732 }
5733
5734 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005735 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005736 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005737
Vishnu Nair47074b82020-08-14 11:54:47 -07005738 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005740 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005741 mWindow->consumeFocusEvent(true);
5742 }
5743
Chris Ye2ad95392020-09-01 13:44:44 -07005744 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005745 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005746 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005747 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005748 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005749
5750 // Window should receive key down event.
5751 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5752 }
5753
5754 void expectKeyRepeatOnce(int32_t repeatCount) {
5755 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5756 InputEvent* repeatEvent = mWindow->consume();
5757 ASSERT_NE(nullptr, repeatEvent);
5758
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005759 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005760
5761 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5762 uint32_t eventAction = repeatKeyEvent->getAction();
5763 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5764 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5765 }
5766
Chris Ye2ad95392020-09-01 13:44:44 -07005767 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005768 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005769 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005770 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005771 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005772
5773 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005774 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005775 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005776 }
5777};
5778
5779TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005780 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005781 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5782 expectKeyRepeatOnce(repeatCount);
5783 }
5784}
5785
5786TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005787 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005788 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5789 expectKeyRepeatOnce(repeatCount);
5790 }
Harry Cutts33476232023-01-30 19:57:29 +00005791 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005792 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005793 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5794 expectKeyRepeatOnce(repeatCount);
5795 }
5796}
5797
5798TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005799 sendAndConsumeKeyDown(/*deviceId=*/1);
5800 expectKeyRepeatOnce(/*repeatCount=*/1);
5801 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005802 mWindow->assertNoEvents();
5803}
5804
5805TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005806 sendAndConsumeKeyDown(/*deviceId=*/1);
5807 expectKeyRepeatOnce(/*repeatCount=*/1);
5808 sendAndConsumeKeyDown(/*deviceId=*/2);
5809 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005810 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005811 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005812 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005813 expectKeyRepeatOnce(/*repeatCount=*/2);
5814 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005815 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005816 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005817 mWindow->assertNoEvents();
5818}
5819
5820TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005821 sendAndConsumeKeyDown(/*deviceId=*/1);
5822 expectKeyRepeatOnce(/*repeatCount=*/1);
5823 sendAndConsumeKeyDown(/*deviceId=*/2);
5824 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005825 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005826 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005827 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005828 mWindow->assertNoEvents();
5829}
5830
liushenxiang42232912021-05-21 20:24:09 +08005831TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5832 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005833 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005834 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005835 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5836 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5837 mWindow->assertNoEvents();
5838}
5839
Garfield Tan1c7bc862020-01-28 13:24:04 -08005840TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005841 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005842 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005843 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5844 InputEvent* repeatEvent = mWindow->consume();
5845 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5846 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5847 IdGenerator::getSource(repeatEvent->getId()));
5848 }
5849}
5850
5851TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005852 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005853 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005854
5855 std::unordered_set<int32_t> idSet;
5856 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5857 InputEvent* repeatEvent = mWindow->consume();
5858 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5859 int32_t id = repeatEvent->getId();
5860 EXPECT_EQ(idSet.end(), idSet.find(id));
5861 idSet.insert(id);
5862 }
5863}
5864
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005865/* Test InputDispatcher for MultiDisplay */
5866class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5867public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005868 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005869 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005870
Chris Yea209fde2020-07-22 13:54:51 -07005871 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005872 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005873 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005874
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 // Set focus window for primary display, but focused display would be second one.
5876 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005877 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005879 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005880 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005881
Chris Yea209fde2020-07-22 13:54:51 -07005882 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005883 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005884 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005885 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005886 // Set focus display to second one.
5887 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5888 // Set focus window for second display.
5889 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005890 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005891 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005892 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005893 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005894 }
5895
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005896 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005897 InputDispatcherTest::TearDown();
5898
Chris Yea209fde2020-07-22 13:54:51 -07005899 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005900 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005901 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005902 windowInSecondary.clear();
5903 }
5904
5905protected:
Chris Yea209fde2020-07-22 13:54:51 -07005906 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005907 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005908 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005909 sp<FakeWindowHandle> windowInSecondary;
5910};
5911
5912TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5913 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005917 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005918 windowInSecondary->assertNoEvents();
5919
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005920 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5922 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005924 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005925 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005926}
5927
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005928TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005929 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5931 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005932 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005933 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005934 windowInSecondary->assertNoEvents();
5935
5936 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005938 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005939 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005940 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005941
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005942 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005943 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005944
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005945 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005946 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005947 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005948
5949 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005950 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005951 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005952 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005953 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005954 windowInSecondary->assertNoEvents();
5955}
5956
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005957// Test per-display input monitors for motion event.
5958TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005959 FakeMonitorReceiver monitorInPrimary =
5960 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5961 FakeMonitorReceiver monitorInSecondary =
5962 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005963
5964 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5966 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005968 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005969 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005970 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005971 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005972
5973 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5975 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005977 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005978 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005979 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005980 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005981
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005982 // Lift up the touch from the second display
5983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5984 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5986 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5987 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5988
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005989 // Test inject a non-pointer motion event.
5990 // If specific a display, it will dispatch to the focused window of particular display,
5991 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5993 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005995 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005996 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005997 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005998 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005999}
6000
6001// Test per-display input monitors for key event.
6002TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006003 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006004 FakeMonitorReceiver monitorInPrimary =
6005 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6006 FakeMonitorReceiver monitorInSecondary =
6007 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006008
6009 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6011 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006012 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006013 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006014 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006015 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006016}
6017
Vishnu Nair958da932020-08-21 17:12:37 -07006018TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6019 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006020 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006021 secondWindowInPrimary->setFocusable(true);
6022 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6023 setFocusedWindow(secondWindowInPrimary);
6024 windowInPrimary->consumeFocusEvent(false);
6025 secondWindowInPrimary->consumeFocusEvent(true);
6026
6027 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6029 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006030 windowInPrimary->assertNoEvents();
6031 windowInSecondary->assertNoEvents();
6032 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6033}
6034
Arthur Hungdfd528e2021-12-08 13:23:04 +00006035TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6036 FakeMonitorReceiver monitorInPrimary =
6037 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6038 FakeMonitorReceiver monitorInSecondary =
6039 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6040
6041 // Test touch down on primary display.
6042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6043 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6045 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6046 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6047
6048 // Test touch down on second display.
6049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6050 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6052 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6053 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6054
6055 // Trigger cancel touch.
6056 mDispatcher->cancelCurrentTouch();
6057 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6058 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6059 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6060 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6061
6062 // Test inject a move motion event, no window/monitor should receive the event.
6063 ASSERT_EQ(InputEventInjectionResult::FAILED,
6064 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6065 ADISPLAY_ID_DEFAULT, {110, 200}))
6066 << "Inject motion event should return InputEventInjectionResult::FAILED";
6067 windowInPrimary->assertNoEvents();
6068 monitorInPrimary.assertNoEvents();
6069
6070 ASSERT_EQ(InputEventInjectionResult::FAILED,
6071 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6072 SECOND_DISPLAY_ID, {110, 200}))
6073 << "Inject motion event should return InputEventInjectionResult::FAILED";
6074 windowInSecondary->assertNoEvents();
6075 monitorInSecondary.assertNoEvents();
6076}
6077
Jackal Guof9696682018-10-05 12:23:23 +08006078class InputFilterTest : public InputDispatcherTest {
6079protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006080 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6081 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006082 NotifyMotionArgs motionArgs;
6083
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006084 motionArgs =
6085 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006086 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006087 motionArgs =
6088 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006089 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006090 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006091 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006092 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
6093 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006094 } else {
6095 mFakePolicy->assertFilterInputEventWasNotCalled();
6096 }
6097 }
6098
6099 void testNotifyKey(bool expectToBeFiltered) {
6100 NotifyKeyArgs keyArgs;
6101
6102 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006103 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006104 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006105 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006106 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006107
6108 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006109 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006110 } else {
6111 mFakePolicy->assertFilterInputEventWasNotCalled();
6112 }
6113 }
6114};
6115
6116// Test InputFilter for MotionEvent
6117TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6118 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6119 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6120 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6121
6122 // Enable InputFilter
6123 mDispatcher->setInputFilterEnabled(true);
6124 // Test touch on both primary and second display, and check if both events are filtered.
6125 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6126 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6127
6128 // Disable InputFilter
6129 mDispatcher->setInputFilterEnabled(false);
6130 // Test touch on both primary and second display, and check if both events aren't filtered.
6131 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6132 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6133}
6134
6135// Test InputFilter for KeyEvent
6136TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6137 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6138 testNotifyKey(/*expectToBeFiltered*/ false);
6139
6140 // Enable InputFilter
6141 mDispatcher->setInputFilterEnabled(true);
6142 // Send a key event, and check if it is filtered.
6143 testNotifyKey(/*expectToBeFiltered*/ true);
6144
6145 // Disable InputFilter
6146 mDispatcher->setInputFilterEnabled(false);
6147 // Send a key event, and check if it isn't filtered.
6148 testNotifyKey(/*expectToBeFiltered*/ false);
6149}
6150
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006151// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6152// logical display coordinate space.
6153TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6154 ui::Transform firstDisplayTransform;
6155 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6156 ui::Transform secondDisplayTransform;
6157 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6158
6159 std::vector<gui::DisplayInfo> displayInfos(2);
6160 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6161 displayInfos[0].transform = firstDisplayTransform;
6162 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6163 displayInfos[1].transform = secondDisplayTransform;
6164
Patrick Williamsd828f302023-04-28 17:52:08 -05006165 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006166
6167 // Enable InputFilter
6168 mDispatcher->setInputFilterEnabled(true);
6169
6170 // Ensure the correct transforms are used for the displays.
6171 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6172 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6173}
6174
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006175class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6176protected:
6177 virtual void SetUp() override {
6178 InputDispatcherTest::SetUp();
6179
6180 /**
6181 * We don't need to enable input filter to test the injected event policy, but we enabled it
6182 * here to make the tests more realistic, since this policy only matters when inputfilter is
6183 * on.
6184 */
6185 mDispatcher->setInputFilterEnabled(true);
6186
6187 std::shared_ptr<InputApplicationHandle> application =
6188 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006189 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6190 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006191
6192 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6193 mWindow->setFocusable(true);
6194 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6195 setFocusedWindow(mWindow);
6196 mWindow->consumeFocusEvent(true);
6197 }
6198
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006199 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6200 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006201 KeyEvent event;
6202
6203 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6204 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6205 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006206 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006207 const int32_t additionalPolicyFlags =
6208 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006210 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006211 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6212 policyFlags | additionalPolicyFlags));
6213
6214 InputEvent* received = mWindow->consume();
6215 ASSERT_NE(nullptr, received);
6216 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006217 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006218 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6219 ASSERT_EQ(flags, keyEvent.getFlags());
6220 }
6221
6222 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6223 int32_t flags) {
6224 MotionEvent event;
6225 PointerProperties pointerProperties[1];
6226 PointerCoords pointerCoords[1];
6227 pointerProperties[0].clear();
6228 pointerProperties[0].id = 0;
6229 pointerCoords[0].clear();
6230 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6231 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6232
6233 ui::Transform identityTransform;
6234 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6235 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6236 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6237 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6238 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006239 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006240 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006241 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6242
6243 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006245 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006246 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6247 policyFlags | additionalPolicyFlags));
6248
6249 InputEvent* received = mWindow->consume();
6250 ASSERT_NE(nullptr, received);
6251 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006252 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006253 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6254 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006255 }
6256
6257private:
6258 sp<FakeWindowHandle> mWindow;
6259};
6260
6261TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006262 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6263 // filter. Without it, the event will no different from a regularly injected event, and the
6264 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006265 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6266 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006267}
6268
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006269TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006270 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006271 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006272 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6273}
6274
6275TEST_F(InputFilterInjectionPolicyTest,
6276 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6277 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006278 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006279 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006280}
6281
6282TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006283 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6284 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006285}
6286
chaviwfd6d3512019-03-25 13:23:49 -07006287class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006288 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006289 InputDispatcherTest::SetUp();
6290
Chris Yea209fde2020-07-22 13:54:51 -07006291 std::shared_ptr<FakeApplicationHandle> application =
6292 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006293 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006294 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006295 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006296
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006297 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006298 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006299 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006300
6301 // Set focused application.
6302 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006303 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006304
6305 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006306 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006307 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006308 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006309 }
6310
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006311 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006312 InputDispatcherTest::TearDown();
6313
6314 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006315 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006316 }
6317
6318protected:
6319 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006320 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006321 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006322};
6323
6324// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6325// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6326// the onPointerDownOutsideFocus callback.
6327TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006329 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6330 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006332 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006333
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006334 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006335 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6336}
6337
6338// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6339// DOWN on the window that doesn't have focus. Ensure no window received the
6340// onPointerDownOutsideFocus callback.
6341TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006343 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006344 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006345 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006346
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006347 ASSERT_TRUE(mDispatcher->waitForIdle());
6348 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006349}
6350
6351// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6352// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6353TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6355 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006356 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006357 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006358
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006359 ASSERT_TRUE(mDispatcher->waitForIdle());
6360 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006361}
6362
6363// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6364// DOWN on the window that already has focus. Ensure no window received the
6365// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006366TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006368 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006369 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006371 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006372
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006373 ASSERT_TRUE(mDispatcher->waitForIdle());
6374 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006375}
6376
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006377// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6378// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6379TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6380 const MotionEvent event =
6381 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6382 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006383 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006384 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6385 .build();
6386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6387 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6388 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6389
6390 ASSERT_TRUE(mDispatcher->waitForIdle());
6391 mFakePolicy->assertOnPointerDownWasNotCalled();
6392 // Ensure that the unfocused window did not receive any FOCUS events.
6393 mUnfocusedWindow->assertNoEvents();
6394}
6395
chaviwaf87b3e2019-10-01 16:59:28 -07006396// These tests ensures we can send touch events to a single client when there are multiple input
6397// windows that point to the same client token.
6398class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6399 virtual void SetUp() override {
6400 InputDispatcherTest::SetUp();
6401
Chris Yea209fde2020-07-22 13:54:51 -07006402 std::shared_ptr<FakeApplicationHandle> application =
6403 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006404 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6405 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006406 mWindow1->setFrame(Rect(0, 0, 100, 100));
6407
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006408 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6409 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006410 mWindow2->setFrame(Rect(100, 100, 200, 200));
6411
Arthur Hung72d8dc32020-03-28 00:48:39 +00006412 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006413 }
6414
6415protected:
6416 sp<FakeWindowHandle> mWindow1;
6417 sp<FakeWindowHandle> mWindow2;
6418
6419 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006420 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006421 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6422 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006423 }
6424
6425 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6426 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006427 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006428 InputEvent* event = window->consume();
6429
6430 ASSERT_NE(nullptr, event) << name.c_str()
6431 << ": consumer should have returned non-NULL event.";
6432
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006433 ASSERT_EQ(InputEventType::MOTION, event->getType())
6434 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006435
6436 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006437 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006438 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006439
6440 for (size_t i = 0; i < points.size(); i++) {
6441 float expectedX = points[i].x;
6442 float expectedY = points[i].y;
6443
6444 EXPECT_EQ(expectedX, motionEvent.getX(i))
6445 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6446 << ", got " << motionEvent.getX(i);
6447 EXPECT_EQ(expectedY, motionEvent.getY(i))
6448 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6449 << ", got " << motionEvent.getY(i);
6450 }
6451 }
chaviw9eaa22c2020-07-01 16:21:27 -07006452
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006453 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006454 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006455 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6456 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006457
6458 // Always consume from window1 since it's the window that has the InputReceiver
6459 consumeMotionEvent(mWindow1, action, expectedPoints);
6460 }
chaviwaf87b3e2019-10-01 16:59:28 -07006461};
6462
6463TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6464 // Touch Window 1
6465 PointF touchedPoint = {10, 10};
6466 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006467 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006468
6469 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006470 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006471
6472 // Touch Window 2
6473 touchedPoint = {150, 150};
6474 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006475 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006476}
6477
chaviw9eaa22c2020-07-01 16:21:27 -07006478TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6479 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006480 mWindow2->setWindowScale(0.5f, 0.5f);
6481
6482 // Touch Window 1
6483 PointF touchedPoint = {10, 10};
6484 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006485 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006486 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006487 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006488
6489 // Touch Window 2
6490 touchedPoint = {150, 150};
6491 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006492 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6493 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006494
chaviw9eaa22c2020-07-01 16:21:27 -07006495 // Update the transform so rotation is set
6496 mWindow2->setWindowTransform(0, -1, 1, 0);
6497 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6498 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006499}
6500
chaviw9eaa22c2020-07-01 16:21:27 -07006501TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006502 mWindow2->setWindowScale(0.5f, 0.5f);
6503
6504 // Touch Window 1
6505 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6506 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006507 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006508
6509 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006510 touchedPoints.push_back(PointF{150, 150});
6511 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006512 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006513
chaviw9eaa22c2020-07-01 16:21:27 -07006514 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006515 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006516 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006517
chaviw9eaa22c2020-07-01 16:21:27 -07006518 // Update the transform so rotation is set for Window 2
6519 mWindow2->setWindowTransform(0, -1, 1, 0);
6520 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006521 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006522}
6523
chaviw9eaa22c2020-07-01 16:21:27 -07006524TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006525 mWindow2->setWindowScale(0.5f, 0.5f);
6526
6527 // Touch Window 1
6528 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6529 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006530 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006531
6532 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006533 touchedPoints.push_back(PointF{150, 150});
6534 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006535
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006536 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006537
6538 // Move both windows
6539 touchedPoints = {{20, 20}, {175, 175}};
6540 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6541 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6542
chaviw9eaa22c2020-07-01 16:21:27 -07006543 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006544
chaviw9eaa22c2020-07-01 16:21:27 -07006545 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006546 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006547 expectedPoints.pop_back();
6548
6549 // Touch Window 2
6550 mWindow2->setWindowTransform(0, -1, 1, 0);
6551 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006552 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006553
6554 // Move both windows
6555 touchedPoints = {{20, 20}, {175, 175}};
6556 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6557 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6558
6559 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006560}
6561
6562TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6563 mWindow1->setWindowScale(0.5f, 0.5f);
6564
6565 // Touch Window 1
6566 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6567 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006568 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006569
6570 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006571 touchedPoints.push_back(PointF{150, 150});
6572 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006573
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006574 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006575
6576 // Move both windows
6577 touchedPoints = {{20, 20}, {175, 175}};
6578 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6579 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6580
chaviw9eaa22c2020-07-01 16:21:27 -07006581 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006582}
6583
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006584/**
6585 * When one of the windows is slippery, the touch should not slip into the other window with the
6586 * same input channel.
6587 */
6588TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6589 mWindow1->setSlippery(true);
6590 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6591
6592 // Touch down in window 1
6593 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6594 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6595 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6596
6597 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6598 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6599 // getting generated.
6600 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6601 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6602
6603 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6604}
6605
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006606/**
6607 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6608 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6609 * that the pointer is hovering over may have a different transform.
6610 */
6611TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6613
6614 // Start hover in window 1
6615 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6616 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6617 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6618 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6619
6620 // Move hover to window 2.
6621 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6622 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6623
6624 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6625 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6626 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6627}
6628
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006629class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6630 virtual void SetUp() override {
6631 InputDispatcherTest::SetUp();
6632
Chris Yea209fde2020-07-22 13:54:51 -07006633 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006634 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006635 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6636 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006637 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006638 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006639 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006640
6641 // Set focused application.
6642 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6643
6644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006645 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006646 mWindow->consumeFocusEvent(true);
6647 }
6648
6649 virtual void TearDown() override {
6650 InputDispatcherTest::TearDown();
6651 mWindow.clear();
6652 }
6653
6654protected:
Chris Yea209fde2020-07-22 13:54:51 -07006655 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006656 sp<FakeWindowHandle> mWindow;
6657 static constexpr PointF WINDOW_LOCATION = {20, 20};
6658
6659 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006661 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6662 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006664 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6665 WINDOW_LOCATION));
6666 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006667
6668 sp<FakeWindowHandle> addSpyWindow() {
6669 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006670 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006671 spy->setTrustedOverlay(true);
6672 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006673 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006674 spy->setDispatchingTimeout(30ms);
6675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6676 return spy;
6677 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006678};
6679
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006680// Send a tap and respond, which should not cause an ANR.
6681TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6682 tapOnWindow();
6683 mWindow->consumeMotionDown();
6684 mWindow->consumeMotionUp();
6685 ASSERT_TRUE(mDispatcher->waitForIdle());
6686 mFakePolicy->assertNotifyAnrWasNotCalled();
6687}
6688
6689// Send a regular key and respond, which should not cause an ANR.
6690TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006692 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6693 ASSERT_TRUE(mDispatcher->waitForIdle());
6694 mFakePolicy->assertNotifyAnrWasNotCalled();
6695}
6696
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006697TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6698 mWindow->setFocusable(false);
6699 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6700 mWindow->consumeFocusEvent(false);
6701
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006702 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006703 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6704 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6705 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006707 // Key will not go to window because we have no focused window.
6708 // The 'no focused window' ANR timer should start instead.
6709
6710 // Now, the focused application goes away.
6711 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6712 // The key should get dropped and there should be no ANR.
6713
6714 ASSERT_TRUE(mDispatcher->waitForIdle());
6715 mFakePolicy->assertNotifyAnrWasNotCalled();
6716}
6717
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006718// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006719// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6720// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006721TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006723 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6724 WINDOW_LOCATION));
6725
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006726 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6727 ASSERT_TRUE(sequenceNum);
6728 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006729 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006731 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006732 mWindow->consumeMotionEvent(
6733 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006734 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006735 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006736}
6737
6738// Send a key to the app and have the app not respond right away.
6739TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6740 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006741 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006742 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6743 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006744 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006745 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006746 ASSERT_TRUE(mDispatcher->waitForIdle());
6747}
6748
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006749// We have a focused application, but no focused window
6750TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006751 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6753 mWindow->consumeFocusEvent(false);
6754
6755 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006757 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6758 WINDOW_LOCATION));
6759 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6760 mDispatcher->waitForIdle();
6761 mFakePolicy->assertNotifyAnrWasNotCalled();
6762
6763 // Once a focused event arrives, we get an ANR for this application
6764 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6765 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006766 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006767 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6768 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006769 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006770 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006771 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006772 ASSERT_TRUE(mDispatcher->waitForIdle());
6773}
6774
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006775/**
6776 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6777 * there will not be an ANR.
6778 */
6779TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6780 mWindow->setFocusable(false);
6781 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6782 mWindow->consumeFocusEvent(false);
6783
6784 KeyEvent event;
6785 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6786 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6787
6788 // Define a valid key down event that is stale (too old).
6789 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6790 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006791 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006792
6793 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6794
6795 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006796 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006797 InputEventInjectionSync::WAIT_FOR_RESULT,
6798 INJECT_EVENT_TIMEOUT, policyFlags);
6799 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6800 << "Injection should fail because the event is stale";
6801
6802 ASSERT_TRUE(mDispatcher->waitForIdle());
6803 mFakePolicy->assertNotifyAnrWasNotCalled();
6804 mWindow->assertNoEvents();
6805}
6806
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006807// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006808// Make sure that we don't notify policy twice about the same ANR.
6809TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006810 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006811 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6812 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813
6814 // Once a focused event arrives, we get an ANR for this application
6815 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6816 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006817 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006818 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6819 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006820 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006821 const std::chrono::duration appTimeout =
6822 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6823 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006824
Vishnu Naire4df8752022-09-08 09:17:55 -07006825 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006826 // ANR should not be raised again. It is up to policy to do that if it desires.
6827 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006828
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006829 // If we now get a focused window, the ANR should stop, but the policy handles that via
6830 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006831 ASSERT_TRUE(mDispatcher->waitForIdle());
6832}
6833
6834// We have a focused application, but no focused window
6835TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006836 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6838 mWindow->consumeFocusEvent(false);
6839
6840 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006841 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006842 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006843 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6844 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006845
Vishnu Naire4df8752022-09-08 09:17:55 -07006846 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6847 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006848
6849 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006850 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006851 ASSERT_TRUE(mDispatcher->waitForIdle());
6852 mWindow->assertNoEvents();
6853}
6854
6855/**
6856 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6857 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6858 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6859 * the ANR mechanism should still work.
6860 *
6861 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6862 * DOWN event, while not responding on the second one.
6863 */
6864TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6865 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6866 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6867 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6868 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6869 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006870 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006871
6872 // Now send ACTION_UP, with identical timestamp
6873 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6874 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6875 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6876 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006877 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006878
6879 // We have now sent down and up. Let's consume first event and then ANR on the second.
6880 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6881 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006882 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006883}
6884
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006885// A spy window can receive an ANR
6886TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6887 sp<FakeWindowHandle> spy = addSpyWindow();
6888
6889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6890 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6891 WINDOW_LOCATION));
6892 mWindow->consumeMotionDown();
6893
6894 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6895 ASSERT_TRUE(sequenceNum);
6896 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006897 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006898
6899 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006900 spy->consumeMotionEvent(
6901 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006902 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006903 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006904}
6905
6906// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006907// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006908TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6909 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006910
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6912 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006913 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006915
6916 // Stuck on the ACTION_UP
6917 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006918 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006919
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006920 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006922 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6923 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006924
6925 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6926 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006927 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006928 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006929 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006930}
6931
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006932// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006933// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006934TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6935 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006936
6937 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006938 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6939 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006940
6941 mWindow->consumeMotionDown();
6942 // Stuck on the ACTION_UP
6943 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006944 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006945
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006946 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006947 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006948 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6949 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006950
6951 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6952 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006953 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006954 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006955 spy->assertNoEvents();
6956}
6957
6958TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6959 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6960
6961 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6962
6963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6964 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6965 WINDOW_LOCATION));
6966
6967 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6968 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6969 ASSERT_TRUE(consumeSeq);
6970
Prabir Pradhanedd96402022-02-15 01:46:16 -08006971 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006972
6973 monitor.finishEvent(*consumeSeq);
6974 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6975
6976 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006977 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006978}
6979
6980// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6981// process events, you don't get an anr. When the window later becomes unresponsive again, you
6982// get an ANR again.
6983// 1. tap -> block on ACTION_UP -> receive ANR
6984// 2. consume all pending events (= queue becomes healthy again)
6985// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6986TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6987 tapOnWindow();
6988
6989 mWindow->consumeMotionDown();
6990 // Block on ACTION_UP
6991 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006992 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006993 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6994 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006995 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006996 mWindow->assertNoEvents();
6997
6998 tapOnWindow();
6999 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007000 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007001 mWindow->consumeMotionUp();
7002
7003 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007004 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007005 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007006 mWindow->assertNoEvents();
7007}
7008
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007009// If a connection remains unresponsive for a while, make sure policy is only notified once about
7010// it.
7011TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007013 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7014 WINDOW_LOCATION));
7015
7016 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007017 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007018 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007019 // 'notifyConnectionUnresponsive' should only be called once per connection
7020 mFakePolicy->assertNotifyAnrWasNotCalled();
7021 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007022 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007023 mWindow->consumeMotionEvent(
7024 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007025 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007026 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007027 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007028 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007029}
7030
7031/**
7032 * If a window is processing a motion event, and then a key event comes in, the key event should
7033 * not to to the focused window until the motion is processed.
7034 *
7035 * Warning!!!
7036 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7037 * and the injection timeout that we specify when injecting the key.
7038 * We must have the injection timeout (10ms) be smaller than
7039 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7040 *
7041 * If that value changes, this test should also change.
7042 */
7043TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7044 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7046
7047 tapOnWindow();
7048 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7049 ASSERT_TRUE(downSequenceNum);
7050 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7051 ASSERT_TRUE(upSequenceNum);
7052 // Don't finish the events yet, and send a key
7053 // Injection will "succeed" because we will eventually give up and send the key to the focused
7054 // window even if motions are still being processed. But because the injection timeout is short,
7055 // we will receive INJECTION_TIMED_OUT as the result.
7056
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007057 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007058 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007059 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7060 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007061 // Key will not be sent to the window, yet, because the window is still processing events
7062 // and the key remains pending, waiting for the touch events to be processed
7063 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7064 ASSERT_FALSE(keySequenceNum);
7065
7066 std::this_thread::sleep_for(500ms);
7067 // if we wait long enough though, dispatcher will give up, and still send the key
7068 // to the focused window, even though we have not yet finished the motion event
7069 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7070 mWindow->finishEvent(*downSequenceNum);
7071 mWindow->finishEvent(*upSequenceNum);
7072}
7073
7074/**
7075 * If a window is processing a motion event, and then a key event comes in, the key event should
7076 * not go to the focused window until the motion is processed.
7077 * If then a new motion comes in, then the pending key event should be going to the currently
7078 * focused window right away.
7079 */
7080TEST_F(InputDispatcherSingleWindowAnr,
7081 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7082 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7083 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7084
7085 tapOnWindow();
7086 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7087 ASSERT_TRUE(downSequenceNum);
7088 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7089 ASSERT_TRUE(upSequenceNum);
7090 // Don't finish the events yet, and send a key
7091 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007093 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7094 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007095 // At this point, key is still pending, and should not be sent to the application yet.
7096 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7097 ASSERT_FALSE(keySequenceNum);
7098
7099 // Now tap down again. It should cause the pending key to go to the focused window right away.
7100 tapOnWindow();
7101 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7102 // the other events yet. We can finish events in any order.
7103 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7104 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7105 mWindow->consumeMotionDown();
7106 mWindow->consumeMotionUp();
7107 mWindow->assertNoEvents();
7108}
7109
7110class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7111 virtual void SetUp() override {
7112 InputDispatcherTest::SetUp();
7113
Chris Yea209fde2020-07-22 13:54:51 -07007114 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007115 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007116 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7117 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007118 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007119 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007120 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007121
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007122 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7123 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007124 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007125 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007126
7127 // Set focused application.
7128 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007129 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007130
7131 // Expect one focus window exist in display.
7132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007133 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007134 mFocusedWindow->consumeFocusEvent(true);
7135 }
7136
7137 virtual void TearDown() override {
7138 InputDispatcherTest::TearDown();
7139
7140 mUnfocusedWindow.clear();
7141 mFocusedWindow.clear();
7142 }
7143
7144protected:
Chris Yea209fde2020-07-22 13:54:51 -07007145 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007146 sp<FakeWindowHandle> mUnfocusedWindow;
7147 sp<FakeWindowHandle> mFocusedWindow;
7148 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7149 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7150 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7151
7152 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7153
7154 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7155
7156private:
7157 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007159 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7160 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007162 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7163 location));
7164 }
7165};
7166
7167// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7168// should be ANR'd first.
7169TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007171 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7172 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007174 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007175 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007176 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007177 // We consumed all events, so no ANR
7178 ASSERT_TRUE(mDispatcher->waitForIdle());
7179 mFakePolicy->assertNotifyAnrWasNotCalled();
7180
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007182 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7183 FOCUSED_WINDOW_LOCATION));
7184 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7185 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007186
7187 const std::chrono::duration timeout =
7188 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007189 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007190 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7191 // sequence to make it consistent
7192 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007193 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007194 mFocusedWindow->consumeMotionDown();
7195 // This cancel is generated because the connection was unresponsive
7196 mFocusedWindow->consumeMotionCancel();
7197 mFocusedWindow->assertNoEvents();
7198 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007199 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007200 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7201 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007202 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007203}
7204
7205// If we have 2 windows with identical timeouts that are both unresponsive,
7206// it doesn't matter which order they should have ANR.
7207// But we should receive ANR for both.
7208TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7209 // Set the timeout for unfocused window to match the focused window
7210 mUnfocusedWindow->setDispatchingTimeout(10ms);
7211 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7212
7213 tapOnFocusedWindow();
7214 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007215 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7216 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7217 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007218
7219 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007220 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7221 mFocusedWindow->getToken() == anrConnectionToken2);
7222 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7223 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007224
7225 ASSERT_TRUE(mDispatcher->waitForIdle());
7226 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007227
7228 mFocusedWindow->consumeMotionDown();
7229 mFocusedWindow->consumeMotionUp();
7230 mUnfocusedWindow->consumeMotionOutside();
7231
Prabir Pradhanedd96402022-02-15 01:46:16 -08007232 sp<IBinder> responsiveToken1, responsiveToken2;
7233 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7234 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007235
7236 // Both applications should be marked as responsive, in any order
7237 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7238 mFocusedWindow->getToken() == responsiveToken2);
7239 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7240 mUnfocusedWindow->getToken() == responsiveToken2);
7241 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007242}
7243
7244// If a window is already not responding, the second tap on the same window should be ignored.
7245// We should also log an error to account for the dropped event (not tested here).
7246// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7247TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7248 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007249 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007250 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007251 // Receive the events, but don't respond
7252 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7253 ASSERT_TRUE(downEventSequenceNum);
7254 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7255 ASSERT_TRUE(upEventSequenceNum);
7256 const std::chrono::duration timeout =
7257 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007258 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007259
7260 // Tap once again
7261 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007262 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007263 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7264 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007265 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007266 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7267 FOCUSED_WINDOW_LOCATION));
7268 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7269 // valid touch target
7270 mUnfocusedWindow->assertNoEvents();
7271
7272 // Consume the first tap
7273 mFocusedWindow->finishEvent(*downEventSequenceNum);
7274 mFocusedWindow->finishEvent(*upEventSequenceNum);
7275 ASSERT_TRUE(mDispatcher->waitForIdle());
7276 // The second tap did not go to the focused window
7277 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007278 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007279 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7280 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007281 mFakePolicy->assertNotifyAnrWasNotCalled();
7282}
7283
7284// If you tap outside of all windows, there will not be ANR
7285TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007286 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007287 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7288 LOCATION_OUTSIDE_ALL_WINDOWS));
7289 ASSERT_TRUE(mDispatcher->waitForIdle());
7290 mFakePolicy->assertNotifyAnrWasNotCalled();
7291}
7292
7293// Since the focused window is paused, tapping on it should not produce any events
7294TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7295 mFocusedWindow->setPaused(true);
7296 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7297
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007299 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7300 FOCUSED_WINDOW_LOCATION));
7301
7302 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7303 ASSERT_TRUE(mDispatcher->waitForIdle());
7304 // Should not ANR because the window is paused, and touches shouldn't go to it
7305 mFakePolicy->assertNotifyAnrWasNotCalled();
7306
7307 mFocusedWindow->assertNoEvents();
7308 mUnfocusedWindow->assertNoEvents();
7309}
7310
7311/**
7312 * If a window is processing a motion event, and then a key event comes in, the key event should
7313 * not to to the focused window until the motion is processed.
7314 * If a different window becomes focused at this time, the key should go to that window instead.
7315 *
7316 * Warning!!!
7317 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7318 * and the injection timeout that we specify when injecting the key.
7319 * We must have the injection timeout (10ms) be smaller than
7320 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7321 *
7322 * If that value changes, this test should also change.
7323 */
7324TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7325 // Set a long ANR timeout to prevent it from triggering
7326 mFocusedWindow->setDispatchingTimeout(2s);
7327 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7328
7329 tapOnUnfocusedWindow();
7330 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7331 ASSERT_TRUE(downSequenceNum);
7332 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7333 ASSERT_TRUE(upSequenceNum);
7334 // Don't finish the events yet, and send a key
7335 // Injection will succeed because we will eventually give up and send the key to the focused
7336 // window even if motions are still being processed.
7337
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007338 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007339 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7340 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007342 // Key will not be sent to the window, yet, because the window is still processing events
7343 // and the key remains pending, waiting for the touch events to be processed
7344 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7345 ASSERT_FALSE(keySequenceNum);
7346
7347 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007348 mFocusedWindow->setFocusable(false);
7349 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007351 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007352
7353 // Focus events should precede the key events
7354 mUnfocusedWindow->consumeFocusEvent(true);
7355 mFocusedWindow->consumeFocusEvent(false);
7356
7357 // Finish the tap events, which should unblock dispatcher
7358 mUnfocusedWindow->finishEvent(*downSequenceNum);
7359 mUnfocusedWindow->finishEvent(*upSequenceNum);
7360
7361 // Now that all queues are cleared and no backlog in the connections, the key event
7362 // can finally go to the newly focused "mUnfocusedWindow".
7363 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7364 mFocusedWindow->assertNoEvents();
7365 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007366 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007367}
7368
7369// When the touch stream is split across 2 windows, and one of them does not respond,
7370// then ANR should be raised and the touch should be canceled for the unresponsive window.
7371// The other window should not be affected by that.
7372TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7373 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007374 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7375 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7376 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007377 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007378 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007379
7380 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007381 mDispatcher->notifyMotion(
7382 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7383 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007384
7385 const std::chrono::duration timeout =
7386 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007387 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007388
7389 mUnfocusedWindow->consumeMotionDown();
7390 mFocusedWindow->consumeMotionDown();
7391 // Focused window may or may not receive ACTION_MOVE
7392 // But it should definitely receive ACTION_CANCEL due to the ANR
7393 InputEvent* event;
7394 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7395 ASSERT_TRUE(moveOrCancelSequenceNum);
7396 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7397 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007398 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007399 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7400 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7401 mFocusedWindow->consumeMotionCancel();
7402 } else {
7403 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7404 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007405 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007406 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7407 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007408
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409 mUnfocusedWindow->assertNoEvents();
7410 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007411 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007412}
7413
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007414/**
7415 * If we have no focused window, and a key comes in, we start the ANR timer.
7416 * The focused application should add a focused window before the timer runs out to prevent ANR.
7417 *
7418 * If the user touches another application during this time, the key should be dropped.
7419 * Next, if a new focused window comes in, without toggling the focused application,
7420 * then no ANR should occur.
7421 *
7422 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7423 * but in some cases the policy may not update the focused application.
7424 */
7425TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7426 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7427 std::make_shared<FakeApplicationHandle>();
7428 focusedApplication->setDispatchingTimeout(60ms);
7429 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7430 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7431 mFocusedWindow->setFocusable(false);
7432
7433 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7434 mFocusedWindow->consumeFocusEvent(false);
7435
7436 // Send a key. The ANR timer should start because there is no focused window.
7437 // 'focusedApplication' will get blamed if this timer completes.
7438 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007439 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007440 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7441 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7442 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007444
7445 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7446 // then the injected touches won't cause the focused event to get dropped.
7447 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7448 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7449 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7450 // For this test, it means that the key would get delivered to the window once it becomes
7451 // focused.
7452 std::this_thread::sleep_for(10ms);
7453
7454 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007455 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7456 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7457 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007458
7459 // We do not consume the motion right away, because that would require dispatcher to first
7460 // process (== drop) the key event, and by that time, ANR will be raised.
7461 // Set the focused window first.
7462 mFocusedWindow->setFocusable(true);
7463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7464 setFocusedWindow(mFocusedWindow);
7465 mFocusedWindow->consumeFocusEvent(true);
7466 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7467 // to another application. This could be a bug / behaviour in the policy.
7468
7469 mUnfocusedWindow->consumeMotionDown();
7470
7471 ASSERT_TRUE(mDispatcher->waitForIdle());
7472 // Should not ANR because we actually have a focused window. It was just added too slowly.
7473 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7474}
7475
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007476// These tests ensure we cannot send touch events to a window that's positioned behind a window
7477// that has feature NO_INPUT_CHANNEL.
7478// Layout:
7479// Top (closest to user)
7480// mNoInputWindow (above all windows)
7481// mBottomWindow
7482// Bottom (furthest from user)
7483class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7484 virtual void SetUp() override {
7485 InputDispatcherTest::SetUp();
7486
7487 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007488 mNoInputWindow =
7489 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7490 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007491 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007492 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007493 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7494 // It's perfectly valid for this window to not have an associated input channel
7495
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007496 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7497 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007498 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7499
7500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7501 }
7502
7503protected:
7504 std::shared_ptr<FakeApplicationHandle> mApplication;
7505 sp<FakeWindowHandle> mNoInputWindow;
7506 sp<FakeWindowHandle> mBottomWindow;
7507};
7508
7509TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7510 PointF touchedPoint = {10, 10};
7511
Prabir Pradhan678438e2023-04-13 19:32:51 +00007512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7513 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7514 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007515
7516 mNoInputWindow->assertNoEvents();
7517 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7518 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7519 // and therefore should prevent mBottomWindow from receiving touches
7520 mBottomWindow->assertNoEvents();
7521}
7522
7523/**
7524 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7525 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7526 */
7527TEST_F(InputDispatcherMultiWindowOcclusionTests,
7528 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007529 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7530 "Window with input channel and NO_INPUT_CHANNEL",
7531 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007532
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007533 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007534 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7535 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7536
7537 PointF touchedPoint = {10, 10};
7538
Prabir Pradhan678438e2023-04-13 19:32:51 +00007539 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7540 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7541 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007542
7543 mNoInputWindow->assertNoEvents();
7544 mBottomWindow->assertNoEvents();
7545}
7546
Vishnu Nair958da932020-08-21 17:12:37 -07007547class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7548protected:
7549 std::shared_ptr<FakeApplicationHandle> mApp;
7550 sp<FakeWindowHandle> mWindow;
7551 sp<FakeWindowHandle> mMirror;
7552
7553 virtual void SetUp() override {
7554 InputDispatcherTest::SetUp();
7555 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007556 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7557 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7558 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007559 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7560 mWindow->setFocusable(true);
7561 mMirror->setFocusable(true);
7562 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7563 }
7564};
7565
7566TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7567 // Request focus on a mirrored window
7568 setFocusedWindow(mMirror);
7569
7570 // window gets focused
7571 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7573 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007574 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7575}
7576
7577// A focused & mirrored window remains focused only if the window and its mirror are both
7578// focusable.
7579TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7580 setFocusedWindow(mMirror);
7581
7582 // window gets focused
7583 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7585 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007586 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7588 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007589 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7590
7591 mMirror->setFocusable(false);
7592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7593
7594 // window loses focus since one of the windows associated with the token in not focusable
7595 mWindow->consumeFocusEvent(false);
7596
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007597 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7598 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007599 mWindow->assertNoEvents();
7600}
7601
7602// A focused & mirrored window remains focused until the window and its mirror both become
7603// invisible.
7604TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7605 setFocusedWindow(mMirror);
7606
7607 // window gets focused
7608 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7610 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007611 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7613 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007614 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7615
7616 mMirror->setVisible(false);
7617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7618
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7620 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007621 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7623 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007624 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7625
7626 mWindow->setVisible(false);
7627 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7628
7629 // window loses focus only after all windows associated with the token become invisible.
7630 mWindow->consumeFocusEvent(false);
7631
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007632 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7633 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007634 mWindow->assertNoEvents();
7635}
7636
7637// A focused & mirrored window remains focused until both windows are removed.
7638TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7639 setFocusedWindow(mMirror);
7640
7641 // window gets focused
7642 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7644 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007645 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7647 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007648 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7649
7650 // single window is removed but the window token remains focused
7651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7652
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7654 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007655 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7657 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007658 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7659
7660 // Both windows are removed
7661 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7662 mWindow->consumeFocusEvent(false);
7663
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007664 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7665 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007666 mWindow->assertNoEvents();
7667}
7668
7669// Focus request can be pending until one window becomes visible.
7670TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7671 // Request focus on an invisible mirror.
7672 mWindow->setVisible(false);
7673 mMirror->setVisible(false);
7674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7675 setFocusedWindow(mMirror);
7676
7677 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007679 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7680 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007681
7682 mMirror->setVisible(true);
7683 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7684
7685 // window gets focused
7686 mWindow->consumeFocusEvent(true);
7687 // window gets the pending key event
7688 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7689}
Prabir Pradhan99987712020-11-10 18:43:05 -08007690
7691class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7692protected:
7693 std::shared_ptr<FakeApplicationHandle> mApp;
7694 sp<FakeWindowHandle> mWindow;
7695 sp<FakeWindowHandle> mSecondWindow;
7696
7697 void SetUp() override {
7698 InputDispatcherTest::SetUp();
7699 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007700 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007701 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007702 mSecondWindow =
7703 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007704 mSecondWindow->setFocusable(true);
7705
7706 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7708
7709 setFocusedWindow(mWindow);
7710 mWindow->consumeFocusEvent(true);
7711 }
7712
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007713 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007714 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007715 }
7716
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007717 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7718 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007719 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007720 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7721 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007722 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007723 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007724 }
7725};
7726
7727TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7728 // Ensure that capture cannot be obtained for unfocused windows.
7729 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7730 mFakePolicy->assertSetPointerCaptureNotCalled();
7731 mSecondWindow->assertNoEvents();
7732
7733 // Ensure that capture can be enabled from the focus window.
7734 requestAndVerifyPointerCapture(mWindow, true);
7735
7736 // Ensure that capture cannot be disabled from a window that does not have capture.
7737 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7738 mFakePolicy->assertSetPointerCaptureNotCalled();
7739
7740 // Ensure that capture can be disabled from the window with capture.
7741 requestAndVerifyPointerCapture(mWindow, false);
7742}
7743
7744TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007745 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007746
7747 setFocusedWindow(mSecondWindow);
7748
7749 // Ensure that the capture disabled event was sent first.
7750 mWindow->consumeCaptureEvent(false);
7751 mWindow->consumeFocusEvent(false);
7752 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007753 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007754
7755 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007756 notifyPointerCaptureChanged({});
7757 notifyPointerCaptureChanged(request);
7758 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007759 mWindow->assertNoEvents();
7760 mSecondWindow->assertNoEvents();
7761 mFakePolicy->assertSetPointerCaptureNotCalled();
7762}
7763
7764TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007765 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007766
7767 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007768 notifyPointerCaptureChanged({});
7769 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007770
7771 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007772 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007773 mWindow->consumeCaptureEvent(false);
7774 mWindow->assertNoEvents();
7775}
7776
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007777TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7778 requestAndVerifyPointerCapture(mWindow, true);
7779
7780 // The first window loses focus.
7781 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007782 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007783 mWindow->consumeCaptureEvent(false);
7784
7785 // Request Pointer Capture from the second window before the notification from InputReader
7786 // arrives.
7787 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007788 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007789
7790 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007791 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007792
7793 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007794 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007795
7796 mSecondWindow->consumeFocusEvent(true);
7797 mSecondWindow->consumeCaptureEvent(true);
7798}
7799
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007800TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7801 // App repeatedly enables and disables capture.
7802 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7803 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7804 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7805 mFakePolicy->assertSetPointerCaptureCalled(false);
7806 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7807 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7808
7809 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7810 // first request is now stale, this should do nothing.
7811 notifyPointerCaptureChanged(firstRequest);
7812 mWindow->assertNoEvents();
7813
7814 // InputReader notifies that the second request was enabled.
7815 notifyPointerCaptureChanged(secondRequest);
7816 mWindow->consumeCaptureEvent(true);
7817}
7818
Prabir Pradhan7092e262022-05-03 16:51:09 +00007819TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7820 requestAndVerifyPointerCapture(mWindow, true);
7821
7822 // App toggles pointer capture off and on.
7823 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7824 mFakePolicy->assertSetPointerCaptureCalled(false);
7825
7826 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7827 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7828
7829 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7830 // preceding "disable" request.
7831 notifyPointerCaptureChanged(enableRequest);
7832
7833 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7834 // any notifications.
7835 mWindow->assertNoEvents();
7836}
7837
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007838class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7839protected:
7840 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007841
7842 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7843 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7844
7845 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7846 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7847
7848 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7849 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7850 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7851 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7852 MAXIMUM_OBSCURING_OPACITY);
7853
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007854 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007855 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007856 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007857
7858 sp<FakeWindowHandle> mTouchWindow;
7859
7860 virtual void SetUp() override {
7861 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007862 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007863 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7864 }
7865
7866 virtual void TearDown() override {
7867 InputDispatcherTest::TearDown();
7868 mTouchWindow.clear();
7869 }
7870
chaviw3277faf2021-05-19 16:45:23 -05007871 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7872 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007873 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007874 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007875 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007876 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007877 return window;
7878 }
7879
7880 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7881 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7882 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007883 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007884 // Generate an arbitrary PID based on the UID
7885 window->setOwnerInfo(1777 + (uid % 10000), uid);
7886 return window;
7887 }
7888
7889 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007890 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7891 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7892 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007893 }
7894};
7895
7896TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007897 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007898 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007899 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007900
7901 touch();
7902
7903 mTouchWindow->assertNoEvents();
7904}
7905
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007906TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007907 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7908 const sp<FakeWindowHandle>& w =
7909 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7910 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7911
7912 touch();
7913
7914 mTouchWindow->assertNoEvents();
7915}
7916
7917TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007918 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7919 const sp<FakeWindowHandle>& w =
7920 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7921 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7922
7923 touch();
7924
7925 w->assertNoEvents();
7926}
7927
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007928TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007929 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7930 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007931
7932 touch();
7933
7934 mTouchWindow->consumeAnyMotionDown();
7935}
7936
7937TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007938 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007939 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007940 w->setFrame(Rect(0, 0, 50, 50));
7941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007942
7943 touch({PointF{100, 100}});
7944
7945 mTouchWindow->consumeAnyMotionDown();
7946}
7947
7948TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007949 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007950 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7952
7953 touch();
7954
7955 mTouchWindow->consumeAnyMotionDown();
7956}
7957
7958TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7959 const sp<FakeWindowHandle>& w =
7960 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7961 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007962
7963 touch();
7964
7965 mTouchWindow->consumeAnyMotionDown();
7966}
7967
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007968TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7969 const sp<FakeWindowHandle>& w =
7970 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7972
7973 touch();
7974
7975 w->assertNoEvents();
7976}
7977
7978/**
7979 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7980 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7981 * window, the occluding window will still receive ACTION_OUTSIDE event.
7982 */
7983TEST_F(InputDispatcherUntrustedTouchesTest,
7984 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7985 const sp<FakeWindowHandle>& w =
7986 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007987 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007988 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7989
7990 touch();
7991
7992 w->consumeMotionOutside();
7993}
7994
7995TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7996 const sp<FakeWindowHandle>& w =
7997 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007998 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007999 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8000
8001 touch();
8002
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008003 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008004}
8005
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008006TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008007 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008008 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8009 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008010 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8011
8012 touch();
8013
8014 mTouchWindow->consumeAnyMotionDown();
8015}
8016
8017TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8018 const sp<FakeWindowHandle>& w =
8019 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8020 MAXIMUM_OBSCURING_OPACITY);
8021 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008022
8023 touch();
8024
8025 mTouchWindow->consumeAnyMotionDown();
8026}
8027
8028TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008029 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008030 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8031 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8033
8034 touch();
8035
8036 mTouchWindow->assertNoEvents();
8037}
8038
8039TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8040 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8041 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008042 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8043 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008044 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008045 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8046 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008047 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8048
8049 touch();
8050
8051 mTouchWindow->assertNoEvents();
8052}
8053
8054TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8055 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8056 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008057 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8058 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008059 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008060 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8061 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8063
8064 touch();
8065
8066 mTouchWindow->consumeAnyMotionDown();
8067}
8068
8069TEST_F(InputDispatcherUntrustedTouchesTest,
8070 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8071 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008072 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8073 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008074 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008075 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8076 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8078
8079 touch();
8080
8081 mTouchWindow->consumeAnyMotionDown();
8082}
8083
8084TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8085 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008086 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8087 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008088 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008089 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8090 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008092
8093 touch();
8094
8095 mTouchWindow->assertNoEvents();
8096}
8097
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008098TEST_F(InputDispatcherUntrustedTouchesTest,
8099 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8100 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008101 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8102 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008103 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008104 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8105 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008106 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8107
8108 touch();
8109
8110 mTouchWindow->assertNoEvents();
8111}
8112
8113TEST_F(InputDispatcherUntrustedTouchesTest,
8114 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8115 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008116 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8117 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008118 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008119 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8120 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8122
8123 touch();
8124
8125 mTouchWindow->consumeAnyMotionDown();
8126}
8127
8128TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8129 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008130 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8131 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8133
8134 touch();
8135
8136 mTouchWindow->consumeAnyMotionDown();
8137}
8138
8139TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8140 const sp<FakeWindowHandle>& w =
8141 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8142 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8143
8144 touch();
8145
8146 mTouchWindow->consumeAnyMotionDown();
8147}
8148
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008149TEST_F(InputDispatcherUntrustedTouchesTest,
8150 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8151 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8152 const sp<FakeWindowHandle>& w =
8153 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8155
8156 touch();
8157
8158 mTouchWindow->assertNoEvents();
8159}
8160
8161TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8162 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8163 const sp<FakeWindowHandle>& w =
8164 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8166
8167 touch();
8168
8169 mTouchWindow->consumeAnyMotionDown();
8170}
8171
8172TEST_F(InputDispatcherUntrustedTouchesTest,
8173 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8174 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8175 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008176 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8177 OPACITY_ABOVE_THRESHOLD);
8178 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8179
8180 touch();
8181
8182 mTouchWindow->consumeAnyMotionDown();
8183}
8184
8185TEST_F(InputDispatcherUntrustedTouchesTest,
8186 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8187 const sp<FakeWindowHandle>& w1 =
8188 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8189 OPACITY_BELOW_THRESHOLD);
8190 const sp<FakeWindowHandle>& w2 =
8191 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8192 OPACITY_BELOW_THRESHOLD);
8193 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8194
8195 touch();
8196
8197 mTouchWindow->assertNoEvents();
8198}
8199
8200/**
8201 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8202 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8203 * (which alone would result in allowing touches) does not affect the blocking behavior.
8204 */
8205TEST_F(InputDispatcherUntrustedTouchesTest,
8206 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8207 const sp<FakeWindowHandle>& wB =
8208 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8209 OPACITY_BELOW_THRESHOLD);
8210 const sp<FakeWindowHandle>& wC =
8211 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8212 OPACITY_BELOW_THRESHOLD);
8213 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8214
8215 touch();
8216
8217 mTouchWindow->assertNoEvents();
8218}
8219
8220/**
8221 * This test is testing that a window from a different UID but with same application token doesn't
8222 * block the touch. Apps can share the application token for close UI collaboration for example.
8223 */
8224TEST_F(InputDispatcherUntrustedTouchesTest,
8225 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8226 const sp<FakeWindowHandle>& w =
8227 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8228 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008229 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8230
8231 touch();
8232
8233 mTouchWindow->consumeAnyMotionDown();
8234}
8235
arthurhungb89ccb02020-12-30 16:19:01 +08008236class InputDispatcherDragTests : public InputDispatcherTest {
8237protected:
8238 std::shared_ptr<FakeApplicationHandle> mApp;
8239 sp<FakeWindowHandle> mWindow;
8240 sp<FakeWindowHandle> mSecondWindow;
8241 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008242 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008243 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8244 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008245
8246 void SetUp() override {
8247 InputDispatcherTest::SetUp();
8248 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008249 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008250 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008251
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008252 mSecondWindow =
8253 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008254 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008255
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008256 mSpyWindow =
8257 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008258 mSpyWindow->setSpy(true);
8259 mSpyWindow->setTrustedOverlay(true);
8260 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8261
arthurhungb89ccb02020-12-30 16:19:01 +08008262 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008264 }
8265
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008266 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8267 switch (fromSource) {
8268 case AINPUT_SOURCE_TOUCHSCREEN:
8269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8270 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8271 ADISPLAY_ID_DEFAULT, {50, 50}))
8272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8273 break;
8274 case AINPUT_SOURCE_STYLUS:
8275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8276 injectMotionEvent(
8277 mDispatcher,
8278 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8279 AINPUT_SOURCE_STYLUS)
8280 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008281 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008282 .x(50)
8283 .y(50))
8284 .build()));
8285 break;
8286 case AINPUT_SOURCE_MOUSE:
8287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8288 injectMotionEvent(
8289 mDispatcher,
8290 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8291 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8292 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008293 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008294 .x(50)
8295 .y(50))
8296 .build()));
8297 break;
8298 default:
8299 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8300 }
arthurhungb89ccb02020-12-30 16:19:01 +08008301
8302 // Window should receive motion event.
8303 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008304 // Spy window should also receive motion event
8305 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008306 }
8307
8308 // Start performing drag, we will create a drag window and transfer touch to it.
8309 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8310 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008311 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008312 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008313 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008314 }
arthurhungb89ccb02020-12-30 16:19:01 +08008315
8316 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008317 mDragWindow =
8318 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008319 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008320 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008321 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008322
8323 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008324 bool transferred =
8325 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008326 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008327 if (transferred) {
8328 mWindow->consumeMotionCancel();
8329 mDragWindow->consumeMotionDown();
8330 }
8331 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008332 }
8333};
8334
8335TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008336 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008337
8338 // Move on window.
8339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8340 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8341 ADISPLAY_ID_DEFAULT, {50, 50}))
8342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8343 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8344 mWindow->consumeDragEvent(false, 50, 50);
8345 mSecondWindow->assertNoEvents();
8346
8347 // Move to another window.
8348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8349 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8350 ADISPLAY_ID_DEFAULT, {150, 50}))
8351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8352 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8353 mWindow->consumeDragEvent(true, 150, 50);
8354 mSecondWindow->consumeDragEvent(false, 50, 50);
8355
8356 // Move back to original window.
8357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8358 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8359 ADISPLAY_ID_DEFAULT, {50, 50}))
8360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8361 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8362 mWindow->consumeDragEvent(false, 50, 50);
8363 mSecondWindow->consumeDragEvent(true, -50, 50);
8364
8365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8366 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8367 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8368 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8369 mWindow->assertNoEvents();
8370 mSecondWindow->assertNoEvents();
8371}
8372
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008373TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008374 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008375
8376 // No cancel event after drag start
8377 mSpyWindow->assertNoEvents();
8378
8379 const MotionEvent secondFingerDownEvent =
8380 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8381 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008382 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8383 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008384 .build();
8385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8386 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8387 InputEventInjectionSync::WAIT_FOR_RESULT))
8388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8389
8390 // Receives cancel for first pointer after next pointer down
8391 mSpyWindow->consumeMotionCancel();
8392 mSpyWindow->consumeMotionDown();
8393
8394 mSpyWindow->assertNoEvents();
8395}
8396
arthurhungf452d0b2021-01-06 00:19:52 +08008397TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008398 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008399
8400 // Move on window.
8401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8402 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8403 ADISPLAY_ID_DEFAULT, {50, 50}))
8404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8405 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8406 mWindow->consumeDragEvent(false, 50, 50);
8407 mSecondWindow->assertNoEvents();
8408
8409 // Move to another window.
8410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8411 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8412 ADISPLAY_ID_DEFAULT, {150, 50}))
8413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8414 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8415 mWindow->consumeDragEvent(true, 150, 50);
8416 mSecondWindow->consumeDragEvent(false, 50, 50);
8417
8418 // drop to another window.
8419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8420 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8421 {150, 50}))
8422 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8423 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8424 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8425 mWindow->assertNoEvents();
8426 mSecondWindow->assertNoEvents();
8427}
8428
arthurhung6d4bed92021-03-17 11:59:33 +08008429TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008430 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008431
8432 // Move on window and keep button pressed.
8433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8434 injectMotionEvent(mDispatcher,
8435 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8436 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008437 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008438 .build()))
8439 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8440 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8441 mWindow->consumeDragEvent(false, 50, 50);
8442 mSecondWindow->assertNoEvents();
8443
8444 // Move to another window and release button, expect to drop item.
8445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8446 injectMotionEvent(mDispatcher,
8447 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8448 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008449 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008450 .build()))
8451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8452 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8453 mWindow->assertNoEvents();
8454 mSecondWindow->assertNoEvents();
8455 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8456
8457 // nothing to the window.
8458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8459 injectMotionEvent(mDispatcher,
8460 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8461 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008463 .build()))
8464 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8465 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8466 mWindow->assertNoEvents();
8467 mSecondWindow->assertNoEvents();
8468}
8469
Arthur Hung54745652022-04-20 07:17:41 +00008470TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008471 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008472
8473 // Set second window invisible.
8474 mSecondWindow->setVisible(false);
8475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8476
8477 // Move on window.
8478 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8479 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8480 ADISPLAY_ID_DEFAULT, {50, 50}))
8481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8482 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8483 mWindow->consumeDragEvent(false, 50, 50);
8484 mSecondWindow->assertNoEvents();
8485
8486 // Move to another window.
8487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8488 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8489 ADISPLAY_ID_DEFAULT, {150, 50}))
8490 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8491 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8492 mWindow->consumeDragEvent(true, 150, 50);
8493 mSecondWindow->assertNoEvents();
8494
8495 // drop to another window.
8496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8497 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8498 {150, 50}))
8499 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8500 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8501 mFakePolicy->assertDropTargetEquals(nullptr);
8502 mWindow->assertNoEvents();
8503 mSecondWindow->assertNoEvents();
8504}
8505
Arthur Hung54745652022-04-20 07:17:41 +00008506TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008507 // Ensure window could track pointerIds if it didn't support split touch.
8508 mWindow->setPreventSplitting(true);
8509
Arthur Hung54745652022-04-20 07:17:41 +00008510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8511 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8512 {50, 50}))
8513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8514 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8515
8516 const MotionEvent secondFingerDownEvent =
8517 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8518 .displayId(ADISPLAY_ID_DEFAULT)
8519 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008520 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8521 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008522 .build();
8523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8524 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8525 InputEventInjectionSync::WAIT_FOR_RESULT))
8526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008527 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008528
8529 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008530 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008531}
8532
8533TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8534 // First down on second window.
8535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8536 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8537 {150, 50}))
8538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8539
8540 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8541
8542 // Second down on first window.
8543 const MotionEvent secondFingerDownEvent =
8544 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8545 .displayId(ADISPLAY_ID_DEFAULT)
8546 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008547 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8548 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008549 .build();
8550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8551 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8552 InputEventInjectionSync::WAIT_FOR_RESULT))
8553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8554 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8555
8556 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008557 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008558
8559 // Move on window.
8560 const MotionEvent secondFingerMoveEvent =
8561 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8562 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008563 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8564 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008565 .build();
8566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8567 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8568 InputEventInjectionSync::WAIT_FOR_RESULT));
8569 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8570 mWindow->consumeDragEvent(false, 50, 50);
8571 mSecondWindow->consumeMotionMove();
8572
8573 // Release the drag pointer should perform drop.
8574 const MotionEvent secondFingerUpEvent =
8575 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008579 .build();
8580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8581 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8582 InputEventInjectionSync::WAIT_FOR_RESULT));
8583 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8584 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8585 mWindow->assertNoEvents();
8586 mSecondWindow->consumeMotionMove();
8587}
8588
Arthur Hung3915c1f2022-05-31 07:17:17 +00008589TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008590 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008591
8592 // Update window of second display.
8593 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008594 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008595 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8596
8597 // Let second display has a touch state.
8598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8599 injectMotionEvent(mDispatcher,
8600 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8601 AINPUT_SOURCE_TOUCHSCREEN)
8602 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008603 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008604 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008605 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008606 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008607 // Update window again.
8608 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8609
8610 // Move on window.
8611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8612 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8613 ADISPLAY_ID_DEFAULT, {50, 50}))
8614 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8615 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8616 mWindow->consumeDragEvent(false, 50, 50);
8617 mSecondWindow->assertNoEvents();
8618
8619 // Move to another window.
8620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8621 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8622 ADISPLAY_ID_DEFAULT, {150, 50}))
8623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8624 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8625 mWindow->consumeDragEvent(true, 150, 50);
8626 mSecondWindow->consumeDragEvent(false, 50, 50);
8627
8628 // drop to another window.
8629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8630 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8631 {150, 50}))
8632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8633 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8634 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8635 mWindow->assertNoEvents();
8636 mSecondWindow->assertNoEvents();
8637}
8638
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008639TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8640 startDrag(true, AINPUT_SOURCE_MOUSE);
8641 // Move on window.
8642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8643 injectMotionEvent(mDispatcher,
8644 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8645 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8646 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008647 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008648 .x(50)
8649 .y(50))
8650 .build()))
8651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8652 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8653 mWindow->consumeDragEvent(false, 50, 50);
8654 mSecondWindow->assertNoEvents();
8655
8656 // Move to another window.
8657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8658 injectMotionEvent(mDispatcher,
8659 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8660 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8661 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008662 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008663 .x(150)
8664 .y(50))
8665 .build()))
8666 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8667 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8668 mWindow->consumeDragEvent(true, 150, 50);
8669 mSecondWindow->consumeDragEvent(false, 50, 50);
8670
8671 // drop to another window.
8672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8673 injectMotionEvent(mDispatcher,
8674 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8675 .buttonState(0)
8676 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008677 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008678 .x(150)
8679 .y(50))
8680 .build()))
8681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8682 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8683 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8684 mWindow->assertNoEvents();
8685 mSecondWindow->assertNoEvents();
8686}
8687
Vishnu Nair062a8672021-09-03 16:07:44 -07008688class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8689
8690TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8693 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008694 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008695 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8696 window->setFocusable(true);
8697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8698 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008699 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008700
8701 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008702 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008703 window->assertNoEvents();
8704
Prabir Pradhan678438e2023-04-13 19:32:51 +00008705 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8706 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008707 window->assertNoEvents();
8708
8709 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008710 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008711 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8712
Prabir Pradhan678438e2023-04-13 19:32:51 +00008713 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008714 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8715
Prabir Pradhan678438e2023-04-13 19:32:51 +00008716 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8717 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008718 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8719 window->assertNoEvents();
8720}
8721
8722TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8723 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8724 std::make_shared<FakeApplicationHandle>();
8725 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008726 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8727 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008728 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8729 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008730 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8733 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008734 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008735 window->setOwnerInfo(222, 222);
8736 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8737 window->setFocusable(true);
8738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8739 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008740 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008741
8742 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008743 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008744 window->assertNoEvents();
8745
Prabir Pradhan678438e2023-04-13 19:32:51 +00008746 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8747 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008748 window->assertNoEvents();
8749
8750 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008751 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8753
Prabir Pradhan678438e2023-04-13 19:32:51 +00008754 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008755 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8756
Prabir Pradhan678438e2023-04-13 19:32:51 +00008757 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8758 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008759 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8760 window->assertNoEvents();
8761}
8762
8763TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8764 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8765 std::make_shared<FakeApplicationHandle>();
8766 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008767 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8768 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008769 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8770 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008771 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008773 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8774 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008775 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008776 window->setOwnerInfo(222, 222);
8777 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8778 window->setFocusable(true);
8779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8780 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008781 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008782
8783 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008784 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008785 window->assertNoEvents();
8786
Prabir Pradhan678438e2023-04-13 19:32:51 +00008787 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8788 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008789 window->assertNoEvents();
8790
8791 // When the window is no longer obscured because it went on top, it should get input
8792 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8793
Prabir Pradhan678438e2023-04-13 19:32:51 +00008794 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008795 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8796
Prabir Pradhan678438e2023-04-13 19:32:51 +00008797 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8798 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008799 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8800 window->assertNoEvents();
8801}
8802
Antonio Kantekf16f2832021-09-28 04:39:20 +00008803class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8804protected:
8805 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008806 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008807 sp<FakeWindowHandle> mWindow;
8808 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008809 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008810
8811 void SetUp() override {
8812 InputDispatcherTest::SetUp();
8813
8814 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008815 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008816 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008817 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008818 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008819 mSecondWindow =
8820 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008821 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008822 mThirdWindow =
8823 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8824 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8825 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008826
8827 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8829 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8830 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008831 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008832
Antonio Kantek15beb512022-06-13 22:35:41 +00008833 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008834 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008835 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008836 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8837 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008838 mThirdWindow->assertNoEvents();
8839 }
8840
8841 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8842 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008843 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008844 SECOND_DISPLAY_ID)) {
8845 mWindow->assertNoEvents();
8846 mSecondWindow->assertNoEvents();
8847 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008848 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008849 }
8850
Antonio Kantek15beb512022-06-13 22:35:41 +00008851 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8852 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008853 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8854 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008855 mWindow->consumeTouchModeEvent(inTouchMode);
8856 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008857 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008858 }
8859};
8860
Antonio Kantek26defcf2022-02-08 01:12:27 +00008861TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008862 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008863 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8864 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008865 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008866}
8867
Antonio Kantek26defcf2022-02-08 01:12:27 +00008868TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8869 const WindowInfo& windowInfo = *mWindow->getInfo();
8870 int32_t ownerPid = windowInfo.ownerPid;
8871 int32_t ownerUid = windowInfo.ownerUid;
8872 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8873 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008874 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008875 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008876 mWindow->assertNoEvents();
8877 mSecondWindow->assertNoEvents();
8878}
8879
8880TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8881 const WindowInfo& windowInfo = *mWindow->getInfo();
8882 int32_t ownerPid = windowInfo.ownerPid;
8883 int32_t ownerUid = windowInfo.ownerUid;
8884 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008885 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008886 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008887}
8888
Antonio Kantekf16f2832021-09-28 04:39:20 +00008889TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008890 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008891 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8892 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008893 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008894 mWindow->assertNoEvents();
8895 mSecondWindow->assertNoEvents();
8896}
8897
Antonio Kantek15beb512022-06-13 22:35:41 +00008898TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8899 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8900 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8901 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008902 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008903 mWindow->assertNoEvents();
8904 mSecondWindow->assertNoEvents();
8905 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8906}
8907
Antonio Kantek48710e42022-03-24 14:19:30 -07008908TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8909 // Interact with the window first.
8910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8911 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8912 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8913
8914 // Then remove focus.
8915 mWindow->setFocusable(false);
8916 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8917
8918 // Assert that caller can switch touch mode by owning one of the last interacted window.
8919 const WindowInfo& windowInfo = *mWindow->getInfo();
8920 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8921 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008922 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008923}
8924
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008925class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8926public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008927 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008928 std::shared_ptr<FakeApplicationHandle> application =
8929 std::make_shared<FakeApplicationHandle>();
8930 std::string name = "Fake Spy ";
8931 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008932 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8933 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008934 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008935 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008936 return spy;
8937 }
8938
8939 sp<FakeWindowHandle> createForeground() {
8940 std::shared_ptr<FakeApplicationHandle> application =
8941 std::make_shared<FakeApplicationHandle>();
8942 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008943 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8944 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008945 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008946 return window;
8947 }
8948
8949private:
8950 int mSpyCount{0};
8951};
8952
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008953using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008954/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008955 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8956 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008957TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8958 ScopedSilentDeath _silentDeath;
8959
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008960 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008961 spy->setTrustedOverlay(false);
8962 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8963 ".* not a trusted overlay");
8964}
8965
8966/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008967 * Input injection into a display with a spy window but no foreground windows should succeed.
8968 */
8969TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008970 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8972
8973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8976 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8977}
8978
8979/**
8980 * Verify the order in which different input windows receive events. The touched foreground window
8981 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8982 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8983 * receive events before ones belows it.
8984 *
8985 * Here, we set up a scenario with four windows in the following Z order from the top:
8986 * spy1, spy2, window, spy3.
8987 * We then inject an event and verify that the foreground "window" receives it first, followed by
8988 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8989 * window.
8990 */
8991TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8992 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008993 auto spy1 = createSpy();
8994 auto spy2 = createSpy();
8995 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008996 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8997 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8998 const size_t numChannels = channels.size();
8999
Michael Wright8e9a8562022-02-09 13:44:29 +00009000 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009001 if (!epollFd.ok()) {
9002 FAIL() << "Failed to create epoll fd";
9003 }
9004
9005 for (size_t i = 0; i < numChannels; i++) {
9006 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9007 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9008 FAIL() << "Failed to add fd to epoll";
9009 }
9010 }
9011
9012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9013 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9015
9016 std::vector<size_t> eventOrder;
9017 std::vector<struct epoll_event> events(numChannels);
9018 for (;;) {
9019 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9020 (100ms).count());
9021 if (nFds < 0) {
9022 FAIL() << "Failed to call epoll_wait";
9023 }
9024 if (nFds == 0) {
9025 break; // epoll_wait timed out
9026 }
9027 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009028 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009029 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009030 channels[i]->consumeMotionDown();
9031 }
9032 }
9033
9034 // Verify the order in which the events were received.
9035 EXPECT_EQ(3u, eventOrder.size());
9036 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9037 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9038 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9039}
9040
9041/**
9042 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9043 */
9044TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9045 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009046 auto spy = createSpy();
9047 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9049
9050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9051 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9053 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9054 spy->assertNoEvents();
9055}
9056
9057/**
9058 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9059 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9060 * to the window.
9061 */
9062TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9063 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009064 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009065 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9066 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9067
9068 // Inject an event outside the spy window's touchable region.
9069 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9070 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9072 window->consumeMotionDown();
9073 spy->assertNoEvents();
9074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9075 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9076 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9077 window->consumeMotionUp();
9078 spy->assertNoEvents();
9079
9080 // Inject an event inside the spy window's touchable region.
9081 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9082 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9083 {5, 10}))
9084 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9085 window->consumeMotionDown();
9086 spy->consumeMotionDown();
9087}
9088
9089/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009090 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009091 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009092 */
9093TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9094 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009095 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009096 auto spy = createSpy();
9097 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009098 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009099 spy->setFrame(Rect{0, 0, 20, 20});
9100 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9101
9102 // Inject an event outside the spy window's frame and touchable region.
9103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009104 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9105 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9107 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009108 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009109}
9110
9111/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009112 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9113 * pointers that are down within its bounds.
9114 */
9115TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9116 auto windowLeft = createForeground();
9117 windowLeft->setFrame({0, 0, 100, 200});
9118 auto windowRight = createForeground();
9119 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009120 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009121 spy->setFrame({0, 0, 200, 200});
9122 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9123
9124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9125 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9126 {50, 50}))
9127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9128 windowLeft->consumeMotionDown();
9129 spy->consumeMotionDown();
9130
9131 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009132 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009133 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009134 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9135 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009136 .build();
9137 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9138 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9139 InputEventInjectionSync::WAIT_FOR_RESULT))
9140 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9141 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009142 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009143}
9144
9145/**
9146 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9147 * the spy should receive the second pointer with ACTION_DOWN.
9148 */
9149TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9150 auto window = createForeground();
9151 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009152 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009153 spyRight->setFrame({100, 0, 200, 200});
9154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9155
9156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9157 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9158 {50, 50}))
9159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9160 window->consumeMotionDown();
9161 spyRight->assertNoEvents();
9162
9163 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009164 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009165 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009166 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9167 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009168 .build();
9169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9170 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9171 InputEventInjectionSync::WAIT_FOR_RESULT))
9172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009173 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009174 spyRight->consumeMotionDown();
9175}
9176
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009177/**
9178 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9179 * windows should be allowed to control split touch.
9180 */
9181TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009182 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009183 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009184 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009185 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009186
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009187 auto window = createForeground();
9188 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009189
9190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9191
9192 // First finger down, no window touched.
9193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9194 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9195 {100, 200}))
9196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9197 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9198 window->assertNoEvents();
9199
9200 // Second finger down on window, the window should receive touch down.
9201 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009202 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009203 .displayId(ADISPLAY_ID_DEFAULT)
9204 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009205 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9206 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009207 .build();
9208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9209 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9210 InputEventInjectionSync::WAIT_FOR_RESULT))
9211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9212
9213 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009214 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009215}
9216
9217/**
9218 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9219 * do not receive key events.
9220 */
9221TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009222 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009223 spy->setFocusable(false);
9224
9225 auto window = createForeground();
9226 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9227 setFocusedWindow(window);
9228 window->consumeFocusEvent(true);
9229
9230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9231 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9232 window->consumeKeyDown(ADISPLAY_ID_NONE);
9233
9234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9235 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9236 window->consumeKeyUp(ADISPLAY_ID_NONE);
9237
9238 spy->assertNoEvents();
9239}
9240
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009241using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9242
9243/**
9244 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9245 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9246 */
9247TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9248 auto window = createForeground();
9249 auto spy1 = createSpy();
9250 auto spy2 = createSpy();
9251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9252
9253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9254 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9256 window->consumeMotionDown();
9257 spy1->consumeMotionDown();
9258 spy2->consumeMotionDown();
9259
9260 // Pilfer pointers from the second spy window.
9261 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9262 spy2->assertNoEvents();
9263 spy1->consumeMotionCancel();
9264 window->consumeMotionCancel();
9265
9266 // The rest of the gesture should only be sent to the second spy window.
9267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9268 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9269 ADISPLAY_ID_DEFAULT))
9270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9271 spy2->consumeMotionMove();
9272 spy1->assertNoEvents();
9273 window->assertNoEvents();
9274}
9275
9276/**
9277 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9278 * in the middle of the gesture.
9279 */
9280TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9281 auto window = createForeground();
9282 auto spy = createSpy();
9283 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9284
9285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9286 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9287 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9288 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9289 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9290
9291 window->releaseChannel();
9292
9293 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9294
9295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9296 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9297 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9298 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9299}
9300
9301/**
9302 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9303 * the spy, but not to any other windows.
9304 */
9305TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9306 auto spy = createSpy();
9307 auto window = createForeground();
9308
9309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9310
9311 // First finger down on the window and the spy.
9312 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9313 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9314 {100, 200}))
9315 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9316 spy->consumeMotionDown();
9317 window->consumeMotionDown();
9318
9319 // Spy window pilfers the pointers.
9320 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9321 window->consumeMotionCancel();
9322
9323 // Second finger down on the window and spy, but the window should not receive the pointer down.
9324 const MotionEvent secondFingerDownEvent =
9325 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9326 .displayId(ADISPLAY_ID_DEFAULT)
9327 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009328 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9329 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009330 .build();
9331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9332 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9333 InputEventInjectionSync::WAIT_FOR_RESULT))
9334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9335
Harry Cutts33476232023-01-30 19:57:29 +00009336 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009337
9338 // Third finger goes down outside all windows, so injection should fail.
9339 const MotionEvent thirdFingerDownEvent =
9340 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9341 .displayId(ADISPLAY_ID_DEFAULT)
9342 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009343 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9344 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9345 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009346 .build();
9347 ASSERT_EQ(InputEventInjectionResult::FAILED,
9348 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9349 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009350 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009351
9352 spy->assertNoEvents();
9353 window->assertNoEvents();
9354}
9355
9356/**
9357 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9358 */
9359TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9360 auto spy = createSpy();
9361 spy->setFrame(Rect(0, 0, 100, 100));
9362 auto window = createForeground();
9363 window->setFrame(Rect(0, 0, 200, 200));
9364
9365 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9366
9367 // First finger down on the window only
9368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9369 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9370 {150, 150}))
9371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9372 window->consumeMotionDown();
9373
9374 // Second finger down on the spy and window
9375 const MotionEvent secondFingerDownEvent =
9376 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9377 .displayId(ADISPLAY_ID_DEFAULT)
9378 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009379 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009381 .build();
9382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9383 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9384 InputEventInjectionSync::WAIT_FOR_RESULT))
9385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9386 spy->consumeMotionDown();
9387 window->consumeMotionPointerDown(1);
9388
9389 // Third finger down on the spy and window
9390 const MotionEvent thirdFingerDownEvent =
9391 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9392 .displayId(ADISPLAY_ID_DEFAULT)
9393 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009394 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9395 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9396 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009397 .build();
9398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9399 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9400 InputEventInjectionSync::WAIT_FOR_RESULT))
9401 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9402 spy->consumeMotionPointerDown(1);
9403 window->consumeMotionPointerDown(2);
9404
9405 // Spy window pilfers the pointers.
9406 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9407 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9408 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9409
9410 spy->assertNoEvents();
9411 window->assertNoEvents();
9412}
9413
9414/**
9415 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9416 * other windows should be canceled. If this results in the cancellation of all pointers for some
9417 * window, then that window should receive ACTION_CANCEL.
9418 */
9419TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9420 auto spy = createSpy();
9421 spy->setFrame(Rect(0, 0, 100, 100));
9422 auto window = createForeground();
9423 window->setFrame(Rect(0, 0, 200, 200));
9424
9425 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9426
9427 // First finger down on both spy and window
9428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9429 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9430 {10, 10}))
9431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9432 window->consumeMotionDown();
9433 spy->consumeMotionDown();
9434
9435 // Second finger down on the spy and window
9436 const MotionEvent secondFingerDownEvent =
9437 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9438 .displayId(ADISPLAY_ID_DEFAULT)
9439 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009440 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9441 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009442 .build();
9443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9444 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9445 InputEventInjectionSync::WAIT_FOR_RESULT))
9446 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9447 spy->consumeMotionPointerDown(1);
9448 window->consumeMotionPointerDown(1);
9449
9450 // Spy window pilfers the pointers.
9451 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9452 window->consumeMotionCancel();
9453
9454 spy->assertNoEvents();
9455 window->assertNoEvents();
9456}
9457
9458/**
9459 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9460 * be sent to other windows
9461 */
9462TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9463 auto spy = createSpy();
9464 spy->setFrame(Rect(0, 0, 100, 100));
9465 auto window = createForeground();
9466 window->setFrame(Rect(0, 0, 200, 200));
9467
9468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9469
9470 // First finger down on both window and spy
9471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9472 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9473 {10, 10}))
9474 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9475 window->consumeMotionDown();
9476 spy->consumeMotionDown();
9477
9478 // Spy window pilfers the pointers.
9479 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9480 window->consumeMotionCancel();
9481
9482 // Second finger down on the window only
9483 const MotionEvent secondFingerDownEvent =
9484 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9485 .displayId(ADISPLAY_ID_DEFAULT)
9486 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009487 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9488 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009489 .build();
9490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9491 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9492 InputEventInjectionSync::WAIT_FOR_RESULT))
9493 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9494 window->consumeMotionDown();
9495 window->assertNoEvents();
9496
9497 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9498 spy->consumeMotionMove();
9499 spy->assertNoEvents();
9500}
9501
Prabir Pradhand65552b2021-10-07 11:23:50 -07009502class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9503public:
9504 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9505 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9506 std::make_shared<FakeApplicationHandle>();
9507 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009508 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9509 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009510 overlay->setFocusable(false);
9511 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009512 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009513 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009514 overlay->setTrustedOverlay(true);
9515
9516 std::shared_ptr<FakeApplicationHandle> application =
9517 std::make_shared<FakeApplicationHandle>();
9518 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009519 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9520 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009521 window->setFocusable(true);
9522 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009523
9524 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9525 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9526 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009527 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009528 return {std::move(overlay), std::move(window)};
9529 }
9530
9531 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009532 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009533 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009534 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009535 }
9536
9537 void sendStylusEvent(int32_t action) {
9538 NotifyMotionArgs motionArgs =
9539 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9540 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009541 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009542 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009543 }
9544};
9545
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009546using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9547
9548TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9549 ScopedSilentDeath _silentDeath;
9550
Prabir Pradhand65552b2021-10-07 11:23:50 -07009551 auto [overlay, window] = setupStylusOverlayScenario();
9552 overlay->setTrustedOverlay(false);
9553 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9554 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9555 ".* not a trusted overlay");
9556}
9557
9558TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9559 auto [overlay, window] = setupStylusOverlayScenario();
9560 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9561
9562 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9563 overlay->consumeMotionDown();
9564 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9565 overlay->consumeMotionUp();
9566
9567 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9568 window->consumeMotionDown();
9569 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9570 window->consumeMotionUp();
9571
9572 overlay->assertNoEvents();
9573 window->assertNoEvents();
9574}
9575
9576TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9577 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009578 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9580
9581 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9582 overlay->consumeMotionDown();
9583 window->consumeMotionDown();
9584 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9585 overlay->consumeMotionUp();
9586 window->consumeMotionUp();
9587
9588 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9589 window->consumeMotionDown();
9590 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9591 window->consumeMotionUp();
9592
9593 overlay->assertNoEvents();
9594 window->assertNoEvents();
9595}
9596
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009597/**
9598 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9599 * The scenario is as follows:
9600 * - The stylus interceptor overlay is configured as a spy window.
9601 * - The stylus interceptor spy receives the start of a new stylus gesture.
9602 * - It pilfers pointers and then configures itself to no longer be a spy.
9603 * - The stylus interceptor continues to receive the rest of the gesture.
9604 */
9605TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9606 auto [overlay, window] = setupStylusOverlayScenario();
9607 overlay->setSpy(true);
9608 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9609
9610 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9611 overlay->consumeMotionDown();
9612 window->consumeMotionDown();
9613
9614 // The interceptor pilfers the pointers.
9615 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9616 window->consumeMotionCancel();
9617
9618 // The interceptor configures itself so that it is no longer a spy.
9619 overlay->setSpy(false);
9620 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9621
9622 // It continues to receive the rest of the stylus gesture.
9623 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9624 overlay->consumeMotionMove();
9625 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9626 overlay->consumeMotionUp();
9627
9628 window->assertNoEvents();
9629}
9630
Prabir Pradhan5735a322022-04-11 17:23:34 +00009631struct User {
9632 int32_t mPid;
9633 int32_t mUid;
9634 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9635 std::unique_ptr<InputDispatcher>& mDispatcher;
9636
9637 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9638 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9639
9640 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9641 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9642 ADISPLAY_ID_DEFAULT, {100, 200},
9643 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9644 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9645 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9646 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9647 }
9648
9649 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009650 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009651 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009652 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009653 mPolicyFlags);
9654 }
9655
9656 sp<FakeWindowHandle> createWindow() const {
9657 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9658 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009659 sp<FakeWindowHandle> window =
9660 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9661 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009662 window->setOwnerInfo(mPid, mUid);
9663 return window;
9664 }
9665};
9666
9667using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9668
9669TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9670 auto owner = User(mDispatcher, 10, 11);
9671 auto window = owner.createWindow();
9672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9673
9674 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9675 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9676 window->consumeMotionDown();
9677
9678 setFocusedWindow(window);
9679 window->consumeFocusEvent(true);
9680
9681 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9682 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9683 window->consumeKeyDown(ADISPLAY_ID_NONE);
9684}
9685
9686TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9687 auto owner = User(mDispatcher, 10, 11);
9688 auto window = owner.createWindow();
9689 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9690
9691 auto rando = User(mDispatcher, 20, 21);
9692 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9693 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9694
9695 setFocusedWindow(window);
9696 window->consumeFocusEvent(true);
9697
9698 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9699 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9700 window->assertNoEvents();
9701}
9702
9703TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9704 auto owner = User(mDispatcher, 10, 11);
9705 auto window = owner.createWindow();
9706 auto spy = owner.createWindow();
9707 spy->setSpy(true);
9708 spy->setTrustedOverlay(true);
9709 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9710
9711 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9712 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9713 spy->consumeMotionDown();
9714 window->consumeMotionDown();
9715}
9716
9717TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9718 auto owner = User(mDispatcher, 10, 11);
9719 auto window = owner.createWindow();
9720
9721 auto rando = User(mDispatcher, 20, 21);
9722 auto randosSpy = rando.createWindow();
9723 randosSpy->setSpy(true);
9724 randosSpy->setTrustedOverlay(true);
9725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9726
9727 // The event is targeted at owner's window, so injection should succeed, but the spy should
9728 // not receive the event.
9729 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9730 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9731 randosSpy->assertNoEvents();
9732 window->consumeMotionDown();
9733}
9734
9735TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9736 auto owner = User(mDispatcher, 10, 11);
9737 auto window = owner.createWindow();
9738
9739 auto rando = User(mDispatcher, 20, 21);
9740 auto randosSpy = rando.createWindow();
9741 randosSpy->setSpy(true);
9742 randosSpy->setTrustedOverlay(true);
9743 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9744
9745 // A user that has injection permission can inject into any window.
9746 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9747 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9748 ADISPLAY_ID_DEFAULT));
9749 randosSpy->consumeMotionDown();
9750 window->consumeMotionDown();
9751
9752 setFocusedWindow(randosSpy);
9753 randosSpy->consumeFocusEvent(true);
9754
9755 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9756 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9757 window->assertNoEvents();
9758}
9759
9760TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9761 auto owner = User(mDispatcher, 10, 11);
9762 auto window = owner.createWindow();
9763
9764 auto rando = User(mDispatcher, 20, 21);
9765 auto randosWindow = rando.createWindow();
9766 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9767 randosWindow->setWatchOutsideTouch(true);
9768 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9769
9770 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9771 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9772 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9773 window->consumeMotionDown();
9774 randosWindow->consumeMotionOutside();
9775}
9776
Garfield Tane84e6f92019-08-29 17:28:41 -07009777} // namespace android::inputdispatcher