blob: 4d7513837a07261382f0d5d1d0ac1057dcc8dae6 [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"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Prabir Pradhan9205e422023-05-16 20:06:13 +000019#include "EventBuilders.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080020
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhan5735a322022-04-11 17:23:34 +000098static constexpr int32_t WINDOW_PID = 999;
99static constexpr int32_t WINDOW_UID = 1001;
100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for the windows created on the secondary display by the test.
102static constexpr int32_t SECONDARY_WINDOW_PID = 1010;
103static constexpr int32_t SECONDARY_WINDOW_UID = 1012;
104
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000105// An arbitrary pid of the gesture monitor window
106static constexpr int32_t MONITOR_PID = 2001;
107
Siarhei Vishniakou289e9242022-02-15 14:50:16 -0800108static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
109
Arthur Hungc539dbb2022-12-08 07:45:36 +0000110static constexpr int expectedWallpaperFlags =
111 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
112
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800113using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
114
chaviwd1c23182019-12-20 18:44:56 -0800115struct PointF {
116 float x;
117 float y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800118 auto operator<=>(const PointF&) const = default;
chaviwd1c23182019-12-20 18:44:56 -0800119};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800120
Gang Wang342c9272020-01-13 13:15:04 -0500121/**
122 * Return a DOWN key event with KEYCODE_A.
123 */
124static KeyEvent getTestKeyEvent() {
125 KeyEvent event;
126
Garfield Tanfbe732e2020-01-24 11:26:14 -0800127 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
128 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
129 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500130 return event;
131}
132
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000133static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) {
134 ASSERT_EQ(expectedAction, receivedAction)
135 << "expected " << MotionEvent::actionToString(expectedAction) << ", got "
136 << MotionEvent::actionToString(receivedAction);
137}
138
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800139MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") {
140 bool matches = action == arg.getAction();
141 if (!matches) {
142 *result_listener << "expected action " << MotionEvent::actionToString(action)
143 << ", but got " << MotionEvent::actionToString(arg.getAction());
144 }
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800145 if (action == AMOTION_EVENT_ACTION_DOWN) {
146 if (!matches) {
147 *result_listener << "; ";
148 }
149 *result_listener << "downTime should match eventTime for ACTION_DOWN events";
150 matches &= arg.getDownTime() == arg.getEventTime();
151 }
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800152 if (action == AMOTION_EVENT_ACTION_CANCEL) {
153 if (!matches) {
154 *result_listener << "; ";
155 }
156 *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
157 matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
158 }
159 return matches;
160}
161
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -0800162MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
163 return arg.getDownTime() == downTime;
164}
165
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800166MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
167 return arg.getDisplayId() == displayId;
168}
169
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800170MATCHER_P(WithDeviceId, deviceId, "InputEvent with specified deviceId") {
171 return arg.getDeviceId() == deviceId;
172}
173
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -0800174MATCHER_P(WithSource, source, "InputEvent with specified source") {
175 *result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
176 << inputEventSourceToString(arg.getSource());
177 return arg.getSource() == source;
178}
179
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800180MATCHER_P(WithFlags, flags, "InputEvent with specified flags") {
181 return arg.getFlags() == flags;
182}
183
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800184MATCHER_P2(WithCoords, x, y, "MotionEvent with specified coordinates") {
185 if (arg.getPointerCount() != 1) {
186 *result_listener << "Expected 1 pointer, got " << arg.getPointerCount();
187 return false;
188 }
Harry Cutts33476232023-01-30 19:57:29 +0000189 return arg.getX(/*pointerIndex=*/0) == x && arg.getY(/*pointerIndex=*/0) == y;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800190}
191
Siarhei Vishniakouf372b812023-02-14 18:06:51 -0800192MATCHER_P(WithPointerCount, pointerCount, "MotionEvent with specified number of pointers") {
193 return arg.getPointerCount() == pointerCount;
194}
195
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -0800196MATCHER_P(WithPointers, pointers, "MotionEvent with specified pointers") {
197 // Build a map for the received pointers, by pointer id
198 std::map<int32_t /*pointerId*/, PointF> actualPointers;
199 for (size_t pointerIndex = 0; pointerIndex < arg.getPointerCount(); pointerIndex++) {
200 const int32_t pointerId = arg.getPointerId(pointerIndex);
201 actualPointers[pointerId] = {arg.getX(pointerIndex), arg.getY(pointerIndex)};
202 }
203 return pointers == actualPointers;
204}
205
Michael Wrightd02c5b62014-02-10 15:10:22 -0800206// --- FakeInputDispatcherPolicy ---
207
208class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
209 InputDispatcherConfiguration mConfig;
210
Prabir Pradhanedd96402022-02-15 01:46:16 -0800211 using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>;
212
Michael Wrightd02c5b62014-02-10 15:10:22 -0800213public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000214 FakeInputDispatcherPolicy() = default;
215 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800216
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800217 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700218 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700219 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700220 EXPECT_EQ(event.getDisplayId(), args.displayId);
221
222 const auto& keyEvent = static_cast<const KeyEvent&>(event);
223 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
224 EXPECT_EQ(keyEvent.getAction(), args.action);
225 });
Jackal Guof9696682018-10-05 12:23:23 +0800226 }
227
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700228 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
229 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700230 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700231 EXPECT_EQ(event.getDisplayId(), args.displayId);
232
233 const auto& motionEvent = static_cast<const MotionEvent&>(event);
234 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
235 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000236 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
237 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700240 });
Jackal Guof9696682018-10-05 12:23:23 +0800241 }
242
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700243 void assertFilterInputEventWasNotCalled() {
244 std::scoped_lock lock(mLock);
245 ASSERT_EQ(nullptr, mFilteredEvent);
246 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800248 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700249 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800250 ASSERT_TRUE(mConfigurationChangedTime)
251 << "Timed out waiting for configuration changed call";
252 ASSERT_EQ(*mConfigurationChangedTime, when);
253 mConfigurationChangedTime = std::nullopt;
254 }
255
256 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700257 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800258 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800259 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800260 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
261 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
262 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
263 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
264 mLastNotifySwitch = std::nullopt;
265 }
266
chaviwfd6d3512019-03-25 13:23:49 -0700267 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700268 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800269 ASSERT_EQ(touchedToken, mOnPointerDownToken);
270 mOnPointerDownToken.clear();
271 }
272
273 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700274 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800275 ASSERT_TRUE(mOnPointerDownToken == nullptr)
276 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700277 }
278
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700279 // This function must be called soon after the expected ANR timer starts,
280 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500281 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700282 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500283 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800284 std::unique_lock lock(mLock);
285 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 ASSERT_NO_FATAL_FAILURE(
288 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700290 }
291
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000292 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800293 const sp<WindowInfoHandle>& window) {
294 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
295 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
296 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500297 }
298
Prabir Pradhanedd96402022-02-15 01:46:16 -0800299 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
300 const sp<IBinder>& expectedToken,
301 int32_t expectedPid) {
302 std::unique_lock lock(mLock);
303 android::base::ScopedLockAssertion assumeLocked(mLock);
304 AnrResult result;
305 ASSERT_NO_FATAL_FAILURE(result =
306 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
307 const auto& [token, pid] = result;
308 ASSERT_EQ(expectedToken, token);
309 ASSERT_EQ(expectedPid, pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 }
311
Prabir Pradhanedd96402022-02-15 01:46:16 -0800312 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000313 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500314 std::unique_lock lock(mLock);
315 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
317 const auto& [token, _] = result;
318 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000319 }
320
Prabir Pradhanedd96402022-02-15 01:46:16 -0800321 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
322 int32_t expectedPid) {
323 std::unique_lock lock(mLock);
324 android::base::ScopedLockAssertion assumeLocked(mLock);
325 AnrResult result;
326 ASSERT_NO_FATAL_FAILURE(
327 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
328 const auto& [token, pid] = result;
329 ASSERT_EQ(expectedToken, token);
330 ASSERT_EQ(expectedPid, pid);
331 }
332
333 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000334 sp<IBinder> getResponsiveWindowToken() {
335 std::unique_lock lock(mLock);
336 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800337 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
338 const auto& [token, _] = result;
339 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700340 }
341
342 void assertNotifyAnrWasNotCalled() {
343 std::scoped_lock lock(mLock);
344 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800345 ASSERT_TRUE(mAnrWindows.empty());
346 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500347 << "ANR was not called, but please also consume the 'connection is responsive' "
348 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700349 }
350
Garfield Tan1c7bc862020-01-28 13:24:04 -0800351 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
352 mConfig.keyRepeatTimeout = timeout;
353 mConfig.keyRepeatDelay = delay;
354 }
355
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000356 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800357 std::unique_lock lock(mLock);
358 base::ScopedLockAssertion assumeLocked(mLock);
359
360 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
361 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000362 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800363 enabled;
364 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000365 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
366 << ") to be called.";
367 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800368 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000369 auto request = *mPointerCaptureRequest;
370 mPointerCaptureRequest.reset();
371 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800372 }
373
374 void assertSetPointerCaptureNotCalled() {
375 std::unique_lock lock(mLock);
376 base::ScopedLockAssertion assumeLocked(mLock);
377
378 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000379 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800380 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000381 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800382 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000383 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800384 }
385
arthurhungf452d0b2021-01-06 00:19:52 +0800386 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
387 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800388 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800389 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800390 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800391 }
392
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800393 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
394 std::unique_lock lock(mLock);
395 base::ScopedLockAssertion assumeLocked(mLock);
396 std::optional<sp<IBinder>> receivedToken =
397 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
398 mNotifyInputChannelBroken);
399 ASSERT_TRUE(receivedToken.has_value());
400 ASSERT_EQ(token, *receivedToken);
401 }
402
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800403 /**
404 * Set policy timeout. A value of zero means next key will not be intercepted.
405 */
406 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
407 mInterceptKeyTimeout = timeout;
408 }
409
Josep del Riob3981622023-04-18 15:49:45 +0000410 void assertUserActivityPoked() {
411 std::scoped_lock lock(mLock);
412 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
413 }
414
415 void assertUserActivityNotPoked() {
416 std::scoped_lock lock(mLock);
417 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
418 }
419
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000420 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<int32_t> uids) {
421 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
422 }
423
424 void assertNotifyDeviceInteractionWasNotCalled() {
425 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
426 }
427
Michael Wrightd02c5b62014-02-10 15:10:22 -0800428private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700429 std::mutex mLock;
430 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
431 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
432 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
433 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800434
Prabir Pradhan99987712020-11-10 18:43:05 -0800435 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000436
437 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800438
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700440 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800441 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
442 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700443 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800444 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
445 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446
arthurhungf452d0b2021-01-06 00:19:52 +0800447 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800448 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000449 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800450
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800451 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
452
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000453 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<int32_t /*uid*/>>> mNotifiedInteractions;
454
Prabir Pradhanedd96402022-02-15 01:46:16 -0800455 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
456 // for a specific container to become non-empty. When the container is non-empty, return the
457 // first entry from the container and erase it.
458 template <class T>
459 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
460 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
461 // If there is an ANR, Dispatcher won't be idle because there are still events
462 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
463 // before checking if ANR was called.
464 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
465 // to provide it some time to act. 100ms seems reasonable.
466 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
467 const std::chrono::time_point start = std::chrono::steady_clock::now();
468 std::optional<T> token =
469 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
470 if (!token.has_value()) {
471 ADD_FAILURE() << "Did not receive the ANR callback";
472 return {};
473 }
474
475 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
476 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
477 // the dispatcher started counting before this function was called
478 if (std::chrono::abs(timeout - waited) > 100ms) {
479 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
480 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
481 << "ms, but waited "
482 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
483 << "ms instead";
484 }
485 return *token;
486 }
487
488 template <class T>
489 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
490 std::queue<T>& storage,
491 std::unique_lock<std::mutex>& lock,
492 std::condition_variable& condition)
493 REQUIRES(mLock) {
494 condition.wait_for(lock, timeout,
495 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
496 if (storage.empty()) {
497 ADD_FAILURE() << "Did not receive the expected callback";
498 return std::nullopt;
499 }
500 T item = storage.front();
501 storage.pop();
502 return std::make_optional(item);
503 }
504
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600505 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700506 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800507 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800508 }
509
Prabir Pradhanedd96402022-02-15 01:46:16 -0800510 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid,
511 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700512 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800513 ASSERT_TRUE(pid.has_value());
514 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700515 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500516 }
517
Prabir Pradhanedd96402022-02-15 01:46:16 -0800518 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
519 std::optional<int32_t> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500520 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800521 ASSERT_TRUE(pid.has_value());
522 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500523 mNotifyAnr.notify_all();
524 }
525
526 void notifyNoFocusedWindowAnr(
527 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
528 std::scoped_lock lock(mLock);
529 mAnrApplications.push(applicationHandle);
530 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800531 }
532
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800533 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
534 std::scoped_lock lock(mLock);
535 mBrokenInputChannels.push(connectionToken);
536 mNotifyInputChannelBroken.notify_all();
537 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800538
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600539 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700540
Chris Yef59a2f42020-10-16 12:55:26 -0700541 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
542 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
543 const std::vector<float>& values) override {}
544
545 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
546 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000547
Chris Yefb552902021-02-03 17:18:37 -0800548 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
549
Prabir Pradhana41d2442023-04-20 21:30:40 +0000550 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Prabir Pradhana41d2442023-04-20 21:30:40 +0000552 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700553 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000554 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000556 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
557 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800558 break;
559 }
560
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700561 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000562 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
563 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800564 break;
565 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700566 default: {
567 ADD_FAILURE() << "Should only filter keys or motions";
568 break;
569 }
Jackal Guof9696682018-10-05 12:23:23 +0800570 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800571 return true;
572 }
573
Prabir Pradhana41d2442023-04-20 21:30:40 +0000574 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
575 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800576 // Clear intercept state when we handled the event.
577 mInterceptKeyTimeout = 0ms;
578 }
579 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800580
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600581 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582
Prabir Pradhana41d2442023-04-20 21:30:40 +0000583 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800584 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
585 // Clear intercept state so we could dispatch the event in next wake.
586 mInterceptKeyTimeout = 0ms;
587 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800588 }
589
Prabir Pradhana41d2442023-04-20 21:30:40 +0000590 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
591 uint32_t) override {
592 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593 }
594
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600595 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
596 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700597 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800598 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
599 * essentially a passthrough for notifySwitch.
600 */
Harry Cutts33476232023-01-30 19:57:29 +0000601 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602 }
603
Josep del Riob3981622023-04-18 15:49:45 +0000604 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
605 std::scoped_lock lock(mLock);
606 mPokedUserActivity = true;
607 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800608
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600609 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700610 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700611 mOnPointerDownToken = newToken;
612 }
613
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000614 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800615 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000616 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800617 mPointerCaptureChangedCondition.notify_all();
618 }
619
arthurhungf452d0b2021-01-06 00:19:52 +0800620 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
621 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800622 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800623 mDropTargetWindowToken = token;
624 }
625
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000626 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
627 const std::set<int32_t>& uids) override {
628 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
629 }
630
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700631 void assertFilterInputEventWasCalledInternal(
632 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700633 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800634 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700635 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800636 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800637 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800638};
639
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640// --- InputDispatcherTest ---
641
642class InputDispatcherTest : public testing::Test {
643protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000644 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700645 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800646
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000647 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000648 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
649 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800650 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000651 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700652 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
654
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000655 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700656 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000657 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700658 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700660
661 /**
662 * Used for debugging when writing the test
663 */
664 void dumpDispatcherState() {
665 std::string dump;
666 mDispatcher->dump(dump);
667 std::stringstream ss(dump);
668 std::string to;
669
670 while (std::getline(ss, to, '\n')) {
671 ALOGE("%s", to.c_str());
672 }
673 }
Vishnu Nair958da932020-08-21 17:12:37 -0700674
Chavi Weingarten847e8512023-03-29 00:26:09 +0000675 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700676 FocusRequest request;
677 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000678 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700679 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
680 request.displayId = window->getInfo()->displayId;
681 mDispatcher->setFocusedWindow(request);
682 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683};
684
Michael Wrightd02c5b62014-02-10 15:10:22 -0800685TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
686 KeyEvent event;
687
688 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800689 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
690 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600691 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
692 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800693 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000694 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000695 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800696 << "Should reject key events with undefined action.";
697
698 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800699 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
700 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600701 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800702 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000703 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000704 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705 << "Should reject key events with ACTION_MULTIPLE.";
706}
707
708TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
709 MotionEvent event;
710 PointerProperties pointerProperties[MAX_POINTERS + 1];
711 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800712 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800713 pointerProperties[i].clear();
714 pointerProperties[i].id = i;
715 pointerCoords[i].clear();
716 }
717
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800718 // Some constants commonly used below
719 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
720 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
721 constexpr int32_t metaState = AMETA_NONE;
722 constexpr MotionClassification classification = MotionClassification::NONE;
723
chaviw9eaa22c2020-07-01 16:21:27 -0700724 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800725 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800726 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700727 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
728 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700729 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
730 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700731 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000733 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000734 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 << "Should reject motion events with undefined action.";
736
737 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800738 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800739 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
740 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
741 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
742 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500743 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800744 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000745 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000746 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800747 << "Should reject motion events with pointer down index too large.";
748
Garfield Tanfbe732e2020-01-24 11:26:14 -0800749 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700750 AMOTION_EVENT_ACTION_POINTER_DOWN |
751 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700752 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
753 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700754 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500755 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800756 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000757 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000758 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800759 << "Should reject motion events with pointer down index too small.";
760
761 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800762 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800763 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
764 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
765 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
766 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500767 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800768 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000769 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000770 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800771 << "Should reject motion events with pointer up index too large.";
772
Garfield Tanfbe732e2020-01-24 11:26:14 -0800773 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700774 AMOTION_EVENT_ACTION_POINTER_UP |
775 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700776 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
777 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700778 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500779 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000781 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000782 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800783 << "Should reject motion events with pointer up index too small.";
784
785 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800786 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
787 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700788 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700789 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
790 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700791 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800792 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000793 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000794 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800795 << "Should reject motion events with 0 pointers.";
796
Garfield Tanfbe732e2020-01-24 11:26:14 -0800797 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
798 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700799 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700800 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
801 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700802 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800803 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000804 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000805 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800806 << "Should reject motion events with more than MAX_POINTERS pointers.";
807
808 // Rejects motion events with invalid pointer ids.
809 pointerProperties[0].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*/ 1, 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 pointer ids less than 0.";
820
821 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800822 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
823 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700824 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700825 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
826 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700827 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800828 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000829 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000830 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800831 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
832
833 // Rejects motion events with duplicate pointer ids.
834 pointerProperties[0].id = 1;
835 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800836 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
837 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700838 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700839 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
840 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700841 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800842 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000843 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000844 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845 << "Should reject motion events with duplicate pointer ids.";
846}
847
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800848/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
849
850TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
851 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000852 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800853 ASSERT_TRUE(mDispatcher->waitForIdle());
854
855 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
856}
857
858TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000859 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
860 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000861 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800862
863 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
864 args.policyFlags |= POLICY_FLAG_TRUSTED;
865 mFakePolicy->assertNotifySwitchWasCalled(args);
866}
867
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700868namespace {
869
Arthur Hungb92218b2018-08-14 12:00:21 +0800870// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700871static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700872// Default input dispatching timeout if there is no focused application or paused window
873// from which to determine an appropriate dispatching timeout.
874static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
875 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
876 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800877
878class FakeApplicationHandle : public InputApplicationHandle {
879public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700880 FakeApplicationHandle() {
881 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700882 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500883 mInfo.dispatchingTimeoutMillis =
884 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700885 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800886 virtual ~FakeApplicationHandle() {}
887
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000888 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700889
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500890 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
891 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700892 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800893};
894
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800895class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800896public:
Garfield Tan15601662020-09-22 15:32:38 -0700897 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800898 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700899 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800900 }
901
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800902 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700903 InputEvent* event;
904 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
905 if (!consumeSeq) {
906 return nullptr;
907 }
908 finishEvent(*consumeSeq);
909 return event;
910 }
911
912 /**
913 * Receive an event without acknowledging it.
914 * Return the sequence number that could later be used to send finished signal.
915 */
916 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917 uint32_t consumeSeq;
918 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800919
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800920 std::chrono::time_point start = std::chrono::steady_clock::now();
921 status_t status = WOULD_BLOCK;
922 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000923 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800924 &event);
925 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
926 if (elapsed > 100ms) {
927 break;
928 }
929 }
930
931 if (status == WOULD_BLOCK) {
932 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700933 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800934 }
935
936 if (status != OK) {
937 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 }
940 if (event == nullptr) {
941 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700942 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 if (outEvent != nullptr) {
945 *outEvent = event;
946 }
947 return consumeSeq;
948 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800949
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700950 /**
951 * To be used together with "receiveEvent" to complete the consumption of an event.
952 */
953 void finishEvent(uint32_t consumeSeq) {
954 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
955 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800956 }
957
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000958 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
959 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
960 ASSERT_EQ(OK, status);
961 }
962
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700963 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000964 std::optional<int32_t> expectedDisplayId,
965 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800966 InputEvent* event = consume();
967
968 ASSERT_NE(nullptr, event) << mName.c_str()
969 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800970 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700971 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
972 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800973
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000974 if (expectedDisplayId.has_value()) {
975 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
976 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800977
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700979 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800980 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
981 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000982 if (expectedFlags.has_value()) {
983 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
984 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800985 break;
986 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700987 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800988 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000989 assertMotionAction(expectedAction, motionEvent.getAction());
990
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedFlags.has_value()) {
992 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994 break;
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100997 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001000 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1001 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001002 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001003 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1004 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001005 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001006 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1007 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001008 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001009 }
1010
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001011 MotionEvent* consumeMotion() {
1012 InputEvent* event = consume();
1013
1014 if (event == nullptr) {
1015 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1016 return nullptr;
1017 }
1018
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001019 if (event->getType() != InputEventType::MOTION) {
1020 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001021 return nullptr;
1022 }
1023 return static_cast<MotionEvent*>(event);
1024 }
1025
1026 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1027 MotionEvent* motionEvent = consumeMotion();
1028 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1029 ASSERT_THAT(*motionEvent, matcher);
1030 }
1031
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1033 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::FOCUS, event->getType())
1037 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038
1039 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1040 << mName.c_str() << ": event displayId should always be NONE.";
1041
1042 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1043 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001044 }
1045
Prabir Pradhan99987712020-11-10 18:43:05 -08001046 void consumeCaptureEvent(bool hasCapture) {
1047 const InputEvent* event = consume();
1048 ASSERT_NE(nullptr, event) << mName.c_str()
1049 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001050 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1051 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001052
1053 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1054 << mName.c_str() << ": event displayId should always be NONE.";
1055
1056 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1057 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1058 }
1059
arthurhungb89ccb02020-12-30 16:19:01 +08001060 void consumeDragEvent(bool isExiting, float x, float y) {
1061 const InputEvent* event = consume();
1062 ASSERT_NE(nullptr, event) << mName.c_str()
1063 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001064 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001065
1066 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1067 << mName.c_str() << ": event displayId should always be NONE.";
1068
1069 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1070 EXPECT_EQ(isExiting, dragEvent.isExiting());
1071 EXPECT_EQ(x, dragEvent.getX());
1072 EXPECT_EQ(y, dragEvent.getY());
1073 }
1074
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075 void consumeTouchModeEvent(bool inTouchMode) {
1076 const InputEvent* event = consume();
1077 ASSERT_NE(nullptr, event) << mName.c_str()
1078 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001079 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1080 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001081
1082 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1083 << mName.c_str() << ": event displayId should always be NONE.";
1084 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1085 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1086 }
1087
chaviwd1c23182019-12-20 18:44:56 -08001088 void assertNoEvents() {
1089 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 if (event == nullptr) {
1091 return;
1092 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001093 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1095 ADD_FAILURE() << "Received key event "
1096 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001097 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001098 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1099 ADD_FAILURE() << "Received motion event "
1100 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001101 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001102 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1103 ADD_FAILURE() << "Received focus event, hasFocus = "
1104 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001105 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001106 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1107 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1108 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001109 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001110 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1111 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1112 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001113 }
1114 FAIL() << mName.c_str()
1115 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001116 }
1117
1118 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1119
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001120 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1121
chaviwd1c23182019-12-20 18:44:56 -08001122protected:
1123 std::unique_ptr<InputConsumer> mConsumer;
1124 PreallocatedInputEventFactory mEventFactory;
1125
1126 std::string mName;
1127};
1128
chaviw3277faf2021-05-19 16:45:23 -05001129class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001130public:
1131 static const int32_t WIDTH = 600;
1132 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001133
Chris Yea209fde2020-07-22 13:54:51 -07001134 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001135 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001136 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001137 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001138 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001139 base::Result<std::unique_ptr<InputChannel>> channel =
1140 dispatcher->createInputChannel(name);
1141 token = (*channel)->getConnectionToken();
1142 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001143 }
1144
1145 inputApplicationHandle->updateInfo();
1146 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1147
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001148 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001149 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001150 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001151 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001152 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001153 mInfo.frameLeft = 0;
1154 mInfo.frameTop = 0;
1155 mInfo.frameRight = WIDTH;
1156 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001157 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001158 mInfo.globalScaleFactor = 1.0;
1159 mInfo.touchableRegion.clear();
1160 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001161 mInfo.ownerPid = WINDOW_PID;
1162 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001163 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001164 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001165 }
1166
Arthur Hungabbb9d82021-09-01 14:52:30 +00001167 sp<FakeWindowHandle> clone(
1168 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001169 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00001170 sp<FakeWindowHandle> handle =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001171 sp<FakeWindowHandle>::make(inputApplicationHandle, dispatcher,
1172 mInfo.name + "(Mirror)", displayId, mInfo.token);
Arthur Hungabbb9d82021-09-01 14:52:30 +00001173 return handle;
1174 }
1175
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001176 void setTouchable(bool touchable) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1178 }
chaviwd1c23182019-12-20 18:44:56 -08001179
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001180 void setFocusable(bool focusable) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1182 }
1183
1184 void setVisible(bool visible) {
1185 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1186 }
Vishnu Nair958da932020-08-21 17:12:37 -07001187
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001188 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001189 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001190 }
1191
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 void setPaused(bool paused) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1194 }
1195
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001196 void setPreventSplitting(bool preventSplitting) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001198 }
1199
1200 void setSlippery(bool slippery) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1202 }
1203
1204 void setWatchOutsideTouch(bool watchOutside) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1206 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001207
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001208 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1209
1210 void setInterceptsStylus(bool interceptsStylus) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1212 }
1213
1214 void setDropInput(bool dropInput) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1216 }
1217
1218 void setDropInputIfObscured(bool dropInputIfObscured) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1220 }
1221
1222 void setNoInputChannel(bool noInputChannel) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1224 }
1225
Josep del Riob3981622023-04-18 15:49:45 +00001226 void setDisableUserActivity(bool disableUserActivity) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1228 }
1229
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001230 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1231
chaviw3277faf2021-05-19 16:45:23 -05001232 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001233
Bernardo Rufino7393d172021-02-26 13:56:11 +00001234 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1235
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001236 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001237 mInfo.frameLeft = frame.left;
1238 mInfo.frameTop = frame.top;
1239 mInfo.frameRight = frame.right;
1240 mInfo.frameBottom = frame.bottom;
1241 mInfo.touchableRegion.clear();
1242 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001243
1244 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1245 ui::Transform translate;
1246 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1247 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001248 }
1249
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001250 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1251
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001252 void setIsWallpaper(bool isWallpaper) {
1253 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1254 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001255
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001256 void setDupTouchToWallpaper(bool hasWallpaper) {
1257 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1258 }
chaviwd1c23182019-12-20 18:44:56 -08001259
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001260 void setTrustedOverlay(bool trustedOverlay) {
1261 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1262 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001263
chaviw9eaa22c2020-07-01 16:21:27 -07001264 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1265 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1266 }
1267
1268 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001269
yunho.shinf4a80b82020-11-16 21:13:57 +09001270 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1271
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001272 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001273 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001274 }
1275
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001276 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001277 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001278 }
1279
Svet Ganov5d3bc372020-01-26 23:11:07 -08001280 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001281 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001282 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1283 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 }
1285
1286 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001288 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1289 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001290 }
1291
1292 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001293 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001294 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1295 }
1296
1297 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1298 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001299 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001300 expectedFlags);
1301 }
1302
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1305 int32_t expectedFlags = 0) {
1306 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1307 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001308 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 }
1310
1311 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedFlags = 0) {
1313 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1314 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001315 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001316 }
1317
1318 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001319 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001320 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001321 expectedFlags);
1322 }
1323
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001324 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1325 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001327 expectedFlags);
1328 }
1329
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001330 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1331 int32_t expectedFlags = 0) {
1332 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001333 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001334 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001335 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1336 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1337 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1338 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1339 }
1340
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001341 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1342 ASSERT_NE(mInputReceiver, nullptr)
1343 << "Cannot consume events from a window with no receiver";
1344 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1345 }
1346
Prabir Pradhan99987712020-11-10 18:43:05 -08001347 void consumeCaptureEvent(bool hasCapture) {
1348 ASSERT_NE(mInputReceiver, nullptr)
1349 << "Cannot consume events from a window with no receiver";
1350 mInputReceiver->consumeCaptureEvent(hasCapture);
1351 }
1352
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001353 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1354 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001355 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001356 ASSERT_THAT(*motionEvent, matcher);
1357 }
1358
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001359 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001360 std::optional<int32_t> expectedDisplayId,
1361 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001362 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1363 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1364 expectedFlags);
1365 }
1366
arthurhungb89ccb02020-12-30 16:19:01 +08001367 void consumeDragEvent(bool isExiting, float x, float y) {
1368 mInputReceiver->consumeDragEvent(isExiting, x, y);
1369 }
1370
Antonio Kantekf16f2832021-09-28 04:39:20 +00001371 void consumeTouchModeEvent(bool inTouchMode) {
1372 ASSERT_NE(mInputReceiver, nullptr)
1373 << "Cannot consume events from a window with no receiver";
1374 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1375 }
1376
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001377 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001378 if (mInputReceiver == nullptr) {
1379 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1380 return std::nullopt;
1381 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001382 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001383 }
1384
1385 void finishEvent(uint32_t sequenceNum) {
1386 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1387 mInputReceiver->finishEvent(sequenceNum);
1388 }
1389
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001390 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1391 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1392 mInputReceiver->sendTimeline(inputEventId, timeline);
1393 }
1394
chaviwaf87b3e2019-10-01 16:59:28 -07001395 InputEvent* consume() {
1396 if (mInputReceiver == nullptr) {
1397 return nullptr;
1398 }
1399 return mInputReceiver->consume();
1400 }
1401
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001402 MotionEvent* consumeMotion() {
1403 InputEvent* event = consume();
1404 if (event == nullptr) {
1405 ADD_FAILURE() << "Consume failed : no event";
1406 return nullptr;
1407 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001408 if (event->getType() != InputEventType::MOTION) {
1409 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001410 return nullptr;
1411 }
1412 return static_cast<MotionEvent*>(event);
1413 }
1414
Arthur Hungb92218b2018-08-14 12:00:21 +08001415 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001416 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001417 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001418 return; // Can't receive events if the window does not have input channel
1419 }
1420 ASSERT_NE(nullptr, mInputReceiver)
1421 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001422 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001423 }
1424
chaviwaf87b3e2019-10-01 16:59:28 -07001425 sp<IBinder> getToken() { return mInfo.token; }
1426
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001427 const std::string& getName() { return mName; }
1428
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001429 void setOwnerInfo(int32_t ownerPid, int32_t ownerUid) {
1430 mInfo.ownerPid = ownerPid;
1431 mInfo.ownerUid = ownerUid;
1432 }
1433
Prabir Pradhanedd96402022-02-15 01:46:16 -08001434 int32_t getPid() const { return mInfo.ownerPid; }
1435
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001436 void destroyReceiver() { mInputReceiver = nullptr; }
1437
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001438 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1439
chaviwd1c23182019-12-20 18:44:56 -08001440private:
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001441 const std::string mName;
chaviwd1c23182019-12-20 18:44:56 -08001442 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001443 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001444};
1445
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001446std::atomic<int32_t> FakeWindowHandle::sId{1};
1447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001448static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001449 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001450 int32_t displayId = ADISPLAY_ID_NONE,
1451 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001452 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001453 bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
1454 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001455 KeyEvent event;
1456 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1457
1458 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001459 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001460 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1461 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001462
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001463 if (!allowKeyRepeat) {
1464 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1465 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001466 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001467 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001468}
1469
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001470static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001471 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001472 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001473}
1474
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001475// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1476// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1477// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001478static InputEventInjectionResult injectKeyDownNoRepeat(
1479 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001480 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001481 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001482 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001483}
1484
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001485static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001486 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001487 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001488}
1489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001490static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001491 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001492 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001493 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
1494 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
1495 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1496 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001497}
1498
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001500 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001501 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001502 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001503 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1504 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001505 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001506 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
1507 std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001508 MotionEventBuilder motionBuilder =
1509 MotionEventBuilder(action, source)
1510 .displayId(displayId)
1511 .eventTime(eventTime)
1512 .rawXCursorPosition(cursorPosition.x)
1513 .rawYCursorPosition(cursorPosition.y)
1514 .pointer(
1515 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1516 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1517 motionBuilder.downTime(eventTime);
1518 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001519
1520 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001521 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1522 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001523}
1524
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001525static InputEventInjectionResult injectMotionDown(
1526 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1527 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001528 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001529}
1530
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001531static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001532 int32_t source, int32_t displayId,
1533 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001534 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001535}
1536
Jackal Guof9696682018-10-05 12:23:23 +08001537static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1538 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1539 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001540 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001541 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1542 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001543
1544 return args;
1545}
1546
Josep del Riob3981622023-04-18 15:49:45 +00001547static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1548 int32_t displayId = ADISPLAY_ID_NONE) {
1549 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1550 // Define a valid key event.
1551 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1552 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1553 currentTime);
1554
1555 return args;
1556}
1557
1558static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1559 int32_t displayId = ADISPLAY_ID_NONE) {
1560 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1561 // Define a valid key event.
1562 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1563 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1564 AMETA_NONE, currentTime);
1565
1566 return args;
1567}
1568
Prabir Pradhan678438e2023-04-13 19:32:51 +00001569[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1570 int32_t displayId,
1571 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001572 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001573 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1574 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1575 }
1576
chaviwd1c23182019-12-20 18:44:56 -08001577 PointerProperties pointerProperties[pointerCount];
1578 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001579
chaviwd1c23182019-12-20 18:44:56 -08001580 for (size_t i = 0; i < pointerCount; i++) {
1581 pointerProperties[i].clear();
1582 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001583 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001584
chaviwd1c23182019-12-20 18:44:56 -08001585 pointerCoords[i].clear();
1586 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1587 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1588 }
Jackal Guof9696682018-10-05 12:23:23 +08001589
1590 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1591 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001592 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001593 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1594 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001595 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1596 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001597 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1598 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001599
1600 return args;
1601}
1602
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001603static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1604 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1605}
1606
chaviwd1c23182019-12-20 18:44:56 -08001607static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1608 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1609}
1610
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001611static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1612 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001613 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001614}
1615
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001616} // namespace
1617
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001618/**
1619 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1620 * broken channel.
1621 */
1622TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1624 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001625 sp<FakeWindowHandle>::make(application, mDispatcher,
1626 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001627
1628 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1629
1630 // Window closes its channel, but the window remains.
1631 window->destroyReceiver();
1632 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1633}
1634
Arthur Hungb92218b2018-08-14 12:00:21 +08001635TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001637 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1638 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001639
Arthur Hung72d8dc32020-03-28 00:48:39 +00001640 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1642 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001644
1645 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001646 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001647}
1648
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001649TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1650 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001651 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1652 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001653
1654 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1655 // Inject a MotionEvent to an unknown display.
1656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1657 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1659
1660 // Window should receive motion event.
1661 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1662}
1663
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001664/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001665 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001666 * This test serves as a sanity check for the next test, where setInputWindows is
1667 * called twice.
1668 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001669TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001671 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1672 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001673 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001674
1675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1678 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001680
1681 // Window should receive motion event.
1682 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1683}
1684
1685/**
1686 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687 */
1688TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1691 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001692 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693
1694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1695 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001697 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1698 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700
1701 // Window should receive motion event.
1702 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1703}
1704
Arthur Hungb92218b2018-08-14 12:00:21 +08001705// The foreground window should receive the first touch down event.
1706TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001708 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001709 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001710 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001711 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001712
Arthur Hung72d8dc32020-03-28 00:48:39 +00001713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1715 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001717
1718 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001719 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001720 windowSecond->assertNoEvents();
1721}
1722
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001723/**
1724 * Two windows: A top window, and a wallpaper behind the window.
1725 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1726 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001727 * 1. foregroundWindow <-- dup touch to wallpaper
1728 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001729 */
1730TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1732 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001733 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001734 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001735 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001736 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001737 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001738
1739 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1741 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1742 {100, 200}))
1743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1744
1745 // Both foreground window and its wallpaper should receive the touch down
1746 foregroundWindow->consumeMotionDown();
1747 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1748
1749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1750 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1751 ADISPLAY_ID_DEFAULT, {110, 200}))
1752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1753
1754 foregroundWindow->consumeMotionMove();
1755 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1756
1757 // Now the foreground window goes away, but the wallpaper stays
1758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1759 foregroundWindow->consumeMotionCancel();
1760 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1761 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1762}
1763
1764/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001765 * Two fingers down on the window, and lift off the first finger.
1766 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1767 * contains a single pointer.
1768 */
1769TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1771 sp<FakeWindowHandle> window =
1772 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1773
1774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001775 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1777 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1778 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001779 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001780 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1781 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1782 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1783 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001784 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001785 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1786 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1787 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1788 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001789 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1790 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1791 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1792
1793 // Remove the window. The gesture should be canceled
1794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1795 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1796 window->consumeMotionEvent(
1797 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1798}
1799
1800/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001801 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1802 * with the following differences:
1803 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1804 * clean up the connection.
1805 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1806 * Ensure that there's no crash in the dispatcher.
1807 */
1808TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1810 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001811 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001812 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001813 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001814 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001815 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001816
1817 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1819 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1820 {100, 200}))
1821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1822
1823 // Both foreground window and its wallpaper should receive the touch down
1824 foregroundWindow->consumeMotionDown();
1825 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1826
1827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1828 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1829 ADISPLAY_ID_DEFAULT, {110, 200}))
1830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1831
1832 foregroundWindow->consumeMotionMove();
1833 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1834
1835 // Wallpaper closes its channel, but the window remains.
1836 wallpaperWindow->destroyReceiver();
1837 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1838
1839 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1840 // is no longer valid.
1841 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1842 foregroundWindow->consumeMotionCancel();
1843}
1844
Arthur Hungc539dbb2022-12-08 07:45:36 +00001845class ShouldSplitTouchFixture : public InputDispatcherTest,
1846 public ::testing::WithParamInterface<bool> {};
1847INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1848 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001849/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001850 * A single window that receives touch (on top), and a wallpaper window underneath it.
1851 * The top window gets a multitouch gesture.
1852 * Ensure that wallpaper gets the same gesture.
1853 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001854TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001856 sp<FakeWindowHandle> foregroundWindow =
1857 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1858 foregroundWindow->setDupTouchToWallpaper(true);
1859 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001860
1861 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001862 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001863 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001864
Arthur Hungc539dbb2022-12-08 07:45:36 +00001865 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866
1867 // Touch down on top window
1868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1869 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1870 {100, 100}))
1871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1872
1873 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001874 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001875 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1876
1877 // Second finger down on the top window
1878 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001879 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001881 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1882 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001883 .build();
1884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1885 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1886 InputEventInjectionSync::WAIT_FOR_RESULT))
1887 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1888
Harry Cutts33476232023-01-30 19:57:29 +00001889 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1890 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001892
1893 const MotionEvent secondFingerUpEvent =
1894 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1895 .displayId(ADISPLAY_ID_DEFAULT)
1896 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001897 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1898 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001899 .build();
1900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1901 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1902 InputEventInjectionSync::WAIT_FOR_RESULT))
1903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1904 foregroundWindow->consumeMotionPointerUp(0);
1905 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1906
1907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001908 injectMotionEvent(mDispatcher,
1909 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1910 AINPUT_SOURCE_TOUCHSCREEN)
1911 .displayId(ADISPLAY_ID_DEFAULT)
1912 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1913 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001914 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001915 .x(100)
1916 .y(100))
1917 .build(),
1918 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1920 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1921 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001922}
1923
1924/**
1925 * Two windows: a window on the left and window on the right.
1926 * A third window, wallpaper, is behind both windows, and spans both top windows.
1927 * The first touch down goes to the left window. A second pointer touches down on the right window.
1928 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1929 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1930 * ACTION_POINTER_DOWN(1).
1931 */
1932TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1934 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001935 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001937 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001938
1939 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001940 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001942 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943
1944 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001945 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001946 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001947 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948
1949 mDispatcher->setInputWindows(
1950 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1951
1952 // Touch down on left window
1953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1954 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1955 {100, 100}))
1956 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1957
1958 // Both foreground window and its wallpaper should receive the touch down
1959 leftWindow->consumeMotionDown();
1960 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1961
1962 // Second finger down on the right window
1963 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001964 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001966 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1967 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 .build();
1969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1970 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1971 InputEventInjectionSync::WAIT_FOR_RESULT))
1972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1973
1974 leftWindow->consumeMotionMove();
1975 // Since the touch is split, right window gets ACTION_DOWN
1976 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001977 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001978 expectedWallpaperFlags);
1979
1980 // Now, leftWindow, which received the first finger, disappears.
1981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1982 leftWindow->consumeMotionCancel();
1983 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1984 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1985
1986 // The pointer that's still down on the right window moves, and goes to the right window only.
1987 // As far as the dispatcher's concerned though, both pointers are still present.
1988 const MotionEvent secondFingerMoveEvent =
1989 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1990 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001991 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1992 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001993 .build();
1994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1995 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1996 InputEventInjectionSync::WAIT_FOR_RESULT));
1997 rightWindow->consumeMotionMove();
1998
1999 leftWindow->assertNoEvents();
2000 rightWindow->assertNoEvents();
2001 wallpaperWindow->assertNoEvents();
2002}
2003
Arthur Hungc539dbb2022-12-08 07:45:36 +00002004/**
2005 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2006 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2007 * The right window should receive ACTION_DOWN.
2008 */
2009TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002011 sp<FakeWindowHandle> leftWindow =
2012 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2013 leftWindow->setFrame(Rect(0, 0, 200, 200));
2014 leftWindow->setDupTouchToWallpaper(true);
2015 leftWindow->setSlippery(true);
2016
2017 sp<FakeWindowHandle> rightWindow =
2018 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2019 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002020
2021 sp<FakeWindowHandle> wallpaperWindow =
2022 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2023 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002024
Arthur Hungc539dbb2022-12-08 07:45:36 +00002025 mDispatcher->setInputWindows(
2026 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002027
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2030 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002031 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033
2034 // Both foreground window and its wallpaper should receive the touch down
2035 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002036 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2037
Arthur Hungc539dbb2022-12-08 07:45:36 +00002038 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002040 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2041 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2043
Arthur Hungc539dbb2022-12-08 07:45:36 +00002044 leftWindow->consumeMotionCancel();
2045 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2046 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002047}
2048
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002049/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002050 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2051 * interactive, it might stop sending this flag.
2052 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2053 * to have a consistent input stream.
2054 *
2055 * Test procedure:
2056 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2057 * DOWN (new gesture).
2058 *
2059 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2060 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2061 *
2062 * We technically just need a single window here, but we are using two windows (spy on top and a
2063 * regular window below) to emulate the actual situation where it happens on the device.
2064 */
2065TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2066 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2067 sp<FakeWindowHandle> spyWindow =
2068 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2069 spyWindow->setFrame(Rect(0, 0, 200, 200));
2070 spyWindow->setTrustedOverlay(true);
2071 spyWindow->setSpy(true);
2072
2073 sp<FakeWindowHandle> window =
2074 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2075 window->setFrame(Rect(0, 0, 200, 200));
2076
2077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2078 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002079
2080 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002081 mDispatcher->notifyMotion(
2082 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2083 .deviceId(touchDeviceId)
2084 .policyFlags(DEFAULT_POLICY_FLAGS)
2085 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2086 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002087
Prabir Pradhan678438e2023-04-13 19:32:51 +00002088 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2089 .deviceId(touchDeviceId)
2090 .policyFlags(DEFAULT_POLICY_FLAGS)
2091 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2092 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2093 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002094 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2095 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2096 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2097 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2098
2099 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(
2101 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2102 .deviceId(touchDeviceId)
2103 .policyFlags(0)
2104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2106 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002107 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2108 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2109
2110 // We don't need to reset the device to reproduce the issue, but the reset event typically
2111 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002113
2114 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002115 mDispatcher->notifyMotion(
2116 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2117 .deviceId(touchDeviceId)
2118 .policyFlags(DEFAULT_POLICY_FLAGS)
2119 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2120 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002121 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2122 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2123
2124 // No more events
2125 spyWindow->assertNoEvents();
2126 window->assertNoEvents();
2127}
2128
2129/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002130 * Two windows: a window on the left and a window on the right.
2131 * Mouse is hovered from the right window into the left window.
2132 * Next, we tap on the left window, where the cursor was last seen.
2133 * The second tap is done onto the right window.
2134 * The mouse and tap are from two different devices.
2135 * We technically don't need to set the downtime / eventtime for these events, but setting these
2136 * explicitly helps during debugging.
2137 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2138 * In the buggy implementation, a tap on the right window would cause a crash.
2139 */
2140TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2142 sp<FakeWindowHandle> leftWindow =
2143 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2144 leftWindow->setFrame(Rect(0, 0, 200, 200));
2145
2146 sp<FakeWindowHandle> rightWindow =
2147 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2148 rightWindow->setFrame(Rect(200, 0, 400, 200));
2149
2150 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2151 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2152 // stale.
2153 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2154 const int32_t mouseDeviceId = 6;
2155 const int32_t touchDeviceId = 4;
2156 // Move the cursor from right
2157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2158 injectMotionEvent(mDispatcher,
2159 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2160 AINPUT_SOURCE_MOUSE)
2161 .deviceId(mouseDeviceId)
2162 .downTime(baseTime + 10)
2163 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002164 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002165 .x(300)
2166 .y(100))
2167 .build()));
2168 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2169
2170 // .. to the left window
2171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2172 injectMotionEvent(mDispatcher,
2173 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2174 AINPUT_SOURCE_MOUSE)
2175 .deviceId(mouseDeviceId)
2176 .downTime(baseTime + 10)
2177 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002178 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002179 .x(110)
2180 .y(100))
2181 .build()));
2182 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2183 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2184 // Now tap the left window
2185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2186 injectMotionEvent(mDispatcher,
2187 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2188 AINPUT_SOURCE_TOUCHSCREEN)
2189 .deviceId(touchDeviceId)
2190 .downTime(baseTime + 40)
2191 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002192 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002193 .x(100)
2194 .y(100))
2195 .build()));
2196 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2197 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2198
2199 // release tap
2200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2201 injectMotionEvent(mDispatcher,
2202 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2203 AINPUT_SOURCE_TOUCHSCREEN)
2204 .deviceId(touchDeviceId)
2205 .downTime(baseTime + 40)
2206 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002207 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002208 .x(100)
2209 .y(100))
2210 .build()));
2211 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2212
2213 // Tap the window on the right
2214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2215 injectMotionEvent(mDispatcher,
2216 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2217 AINPUT_SOURCE_TOUCHSCREEN)
2218 .deviceId(touchDeviceId)
2219 .downTime(baseTime + 60)
2220 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002221 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002222 .x(300)
2223 .y(100))
2224 .build()));
2225 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2226
2227 // release tap
2228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2229 injectMotionEvent(mDispatcher,
2230 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2231 AINPUT_SOURCE_TOUCHSCREEN)
2232 .deviceId(touchDeviceId)
2233 .downTime(baseTime + 60)
2234 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002235 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002236 .x(300)
2237 .y(100))
2238 .build()));
2239 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2240
2241 // No more events
2242 leftWindow->assertNoEvents();
2243 rightWindow->assertNoEvents();
2244}
2245
2246/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002247 * Start hovering in a window. While this hover is still active, make another window appear on top.
2248 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2249 * While the top window is present, the hovering is stopped.
2250 * Later, hovering gets resumed again.
2251 * Ensure that new hover gesture is handled correctly.
2252 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2253 * to the window that's currently being hovered over.
2254 */
2255TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2257 sp<FakeWindowHandle> window =
2258 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2259 window->setFrame(Rect(0, 0, 200, 200));
2260
2261 // Only a single window is present at first
2262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2263
2264 // Start hovering in the window
2265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2266 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2267 .build());
2268 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2269
2270 // Now, an obscuring window appears!
2271 sp<FakeWindowHandle> obscuringWindow =
2272 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2273 ADISPLAY_ID_DEFAULT,
2274 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2275 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2276 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2277 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2278 obscuringWindow->setNoInputChannel(true);
2279 obscuringWindow->setFocusable(false);
2280 obscuringWindow->setAlpha(1.0);
2281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2282
2283 // While this new obscuring window is present, the hovering is stopped
2284 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2285 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2286 .build());
2287 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2288
2289 // Now the obscuring window goes away.
2290 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2291
2292 // And a new hover gesture starts.
2293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2294 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2295 .build());
2296 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2297}
2298
2299/**
2300 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2301 * the obscuring window.
2302 */
2303TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2305 sp<FakeWindowHandle> window =
2306 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2307 window->setFrame(Rect(0, 0, 200, 200));
2308
2309 // Only a single window is present at first
2310 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2311
2312 // Start hovering in the window
2313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2314 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2315 .build());
2316 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2317
2318 // Now, an obscuring window appears!
2319 sp<FakeWindowHandle> obscuringWindow =
2320 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2321 ADISPLAY_ID_DEFAULT,
2322 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2323 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2324 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2325 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2326 obscuringWindow->setNoInputChannel(true);
2327 obscuringWindow->setFocusable(false);
2328 obscuringWindow->setAlpha(1.0);
2329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2330
2331 // While this new obscuring window is present, the hovering continues. The event can't go to the
2332 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2334 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2335 .build());
2336 obscuringWindow->assertNoEvents();
2337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2338
2339 // Now the obscuring window goes away.
2340 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2341
2342 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2343 // so it should generate a HOVER_ENTER
2344 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2345 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2346 .build());
2347 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2348
2349 // Now the MOVE should be getting dispatched normally
2350 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2351 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2352 .build());
2353 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2354}
2355
2356/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002357 * Two windows: a window on the left and a window on the right.
2358 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2359 * down. Then, on the left window, also place second touch pointer down.
2360 * This test tries to reproduce a crash.
2361 * In the buggy implementation, second pointer down on the left window would cause a crash.
2362 */
2363TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2365 sp<FakeWindowHandle> leftWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2367 leftWindow->setFrame(Rect(0, 0, 200, 200));
2368
2369 sp<FakeWindowHandle> rightWindow =
2370 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2371 rightWindow->setFrame(Rect(200, 0, 400, 200));
2372
2373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2374
2375 const int32_t touchDeviceId = 4;
2376 const int32_t mouseDeviceId = 6;
2377 NotifyMotionArgs args;
2378
2379 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2381 .deviceId(mouseDeviceId)
2382 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2383 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002384 leftWindow->consumeMotionEvent(
2385 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2386
2387 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002388 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2389 .deviceId(mouseDeviceId)
2390 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2391 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2392 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002393
2394 leftWindow->consumeMotionEvent(
2395 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2396 leftWindow->consumeMotionEvent(
2397 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2398
Prabir Pradhan678438e2023-04-13 19:32:51 +00002399 mDispatcher->notifyMotion(
2400 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2401 .deviceId(mouseDeviceId)
2402 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2403 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2405 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002406 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2407
2408 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2410 .deviceId(touchDeviceId)
2411 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2412 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002413 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2414
2415 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2416
2417 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002418 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2419 .deviceId(touchDeviceId)
2420 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2421 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2422 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002423 leftWindow->consumeMotionEvent(
2424 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2425 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2426 // current implementation.
2427 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2428 rightWindow->consumeMotionEvent(
2429 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2430
2431 leftWindow->assertNoEvents();
2432 rightWindow->assertNoEvents();
2433}
2434
2435/**
2436 * On a single window, use two different devices: mouse and touch.
2437 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2438 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2439 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2440 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2441 * represent a new gesture.
2442 */
2443TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2444 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2445 sp<FakeWindowHandle> window =
2446 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2447 window->setFrame(Rect(0, 0, 400, 400));
2448
2449 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2450
2451 const int32_t touchDeviceId = 4;
2452 const int32_t mouseDeviceId = 6;
2453 NotifyMotionArgs args;
2454
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002455 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2457 .deviceId(touchDeviceId)
2458 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2459 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002460 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002461 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2462 .deviceId(touchDeviceId)
2463 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2464 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2465 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002466 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002467 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2468 .deviceId(touchDeviceId)
2469 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2470 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2471 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002472 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2473 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2474 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2475
2476 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2478 .deviceId(mouseDeviceId)
2479 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2480 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002482
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002484 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2486
Prabir Pradhan678438e2023-04-13 19:32:51 +00002487 mDispatcher->notifyMotion(
2488 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2489 .deviceId(mouseDeviceId)
2490 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2491 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2495
2496 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002497 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2498 .deviceId(touchDeviceId)
2499 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2500 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2501 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002502 // The pointer_down event should be ignored
2503 window->assertNoEvents();
2504}
2505
2506/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002507 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2508 * the injected event.
2509 */
2510TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2512 sp<FakeWindowHandle> window =
2513 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2514 window->setFrame(Rect(0, 0, 400, 400));
2515
2516 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2517
2518 const int32_t touchDeviceId = 4;
2519 NotifyMotionArgs args;
2520 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2521 // completion.
2522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2523 injectMotionEvent(mDispatcher,
2524 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2525 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002526 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002527 .x(50)
2528 .y(50))
2529 .build()));
2530 window->consumeMotionEvent(
2531 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2532
2533 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2534 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2536 .deviceId(touchDeviceId)
2537 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2538 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002539
2540 window->consumeMotionEvent(
2541 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2542 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2543}
2544
2545/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002546 * This test is similar to the test above, but the sequence of injected events is different.
2547 *
2548 * Two windows: a window on the left and a window on the right.
2549 * Mouse is hovered over the left window.
2550 * Next, we tap on the left window, where the cursor was last seen.
2551 *
2552 * After that, we inject one finger down onto the right window, and then a second finger down onto
2553 * the left window.
2554 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2555 * window (first), and then another on the left window (second).
2556 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2557 * In the buggy implementation, second finger down on the left window would cause a crash.
2558 */
2559TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2561 sp<FakeWindowHandle> leftWindow =
2562 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2563 leftWindow->setFrame(Rect(0, 0, 200, 200));
2564
2565 sp<FakeWindowHandle> rightWindow =
2566 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2567 rightWindow->setFrame(Rect(200, 0, 400, 200));
2568
2569 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2570
2571 const int32_t mouseDeviceId = 6;
2572 const int32_t touchDeviceId = 4;
2573 // Hover over the left window. Keep the cursor there.
2574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2575 injectMotionEvent(mDispatcher,
2576 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2577 AINPUT_SOURCE_MOUSE)
2578 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002579 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002580 .x(50)
2581 .y(50))
2582 .build()));
2583 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2584
2585 // Tap on left window
2586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2587 injectMotionEvent(mDispatcher,
2588 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2589 AINPUT_SOURCE_TOUCHSCREEN)
2590 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002591 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002592 .x(100)
2593 .y(100))
2594 .build()));
2595
2596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2597 injectMotionEvent(mDispatcher,
2598 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2599 AINPUT_SOURCE_TOUCHSCREEN)
2600 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002601 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002602 .x(100)
2603 .y(100))
2604 .build()));
2605 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2606 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2607 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2608
2609 // First finger down on right window
2610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2611 injectMotionEvent(mDispatcher,
2612 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2613 AINPUT_SOURCE_TOUCHSCREEN)
2614 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002615 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002616 .x(300)
2617 .y(100))
2618 .build()));
2619 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2620
2621 // Second finger down on the left window
2622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2623 injectMotionEvent(mDispatcher,
2624 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2625 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002626 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002627 .x(300)
2628 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002629 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002630 .x(100)
2631 .y(100))
2632 .build()));
2633 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2634 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2635
2636 // No more events
2637 leftWindow->assertNoEvents();
2638 rightWindow->assertNoEvents();
2639}
2640
2641/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002642 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2643 * While the touch is down, new hover events from the stylus device should be ignored. After the
2644 * touch is gone, stylus hovering should start working again.
2645 */
2646TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2648 sp<FakeWindowHandle> window =
2649 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2650 window->setFrame(Rect(0, 0, 200, 200));
2651
2652 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2653
2654 const int32_t stylusDeviceId = 5;
2655 const int32_t touchDeviceId = 4;
2656 // Start hovering with stylus
2657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2658 injectMotionEvent(mDispatcher,
2659 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2660 AINPUT_SOURCE_STYLUS)
2661 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002662 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002663 .x(50)
2664 .y(50))
2665 .build()));
2666 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2667
2668 // Finger down on the window
2669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2670 injectMotionEvent(mDispatcher,
2671 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2672 AINPUT_SOURCE_TOUCHSCREEN)
2673 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002674 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002675 .x(100)
2676 .y(100))
2677 .build()));
2678 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2679 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2680
2681 // Try to continue hovering with stylus. Since we are already down, injection should fail
2682 ASSERT_EQ(InputEventInjectionResult::FAILED,
2683 injectMotionEvent(mDispatcher,
2684 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2685 AINPUT_SOURCE_STYLUS)
2686 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002687 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002688 .x(50)
2689 .y(50))
2690 .build()));
2691 // No event should be sent. This event should be ignored because a pointer from another device
2692 // is already down.
2693
2694 // Lift up the finger
2695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2696 injectMotionEvent(mDispatcher,
2697 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2698 AINPUT_SOURCE_TOUCHSCREEN)
2699 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002700 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002701 .x(100)
2702 .y(100))
2703 .build()));
2704 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2705
2706 // Now that the touch is gone, stylus hovering should start working again
2707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2708 injectMotionEvent(mDispatcher,
2709 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2710 AINPUT_SOURCE_STYLUS)
2711 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002712 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002713 .x(50)
2714 .y(50))
2715 .build()));
2716 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2717 // No more events
2718 window->assertNoEvents();
2719}
2720
2721/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 * A spy window above a window with no input channel.
2723 * Start hovering with a stylus device, and then tap with it.
2724 * Ensure spy window receives the entire sequence.
2725 */
2726TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2728 sp<FakeWindowHandle> spyWindow =
2729 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2730 spyWindow->setFrame(Rect(0, 0, 200, 200));
2731 spyWindow->setTrustedOverlay(true);
2732 spyWindow->setSpy(true);
2733 sp<FakeWindowHandle> window =
2734 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2735 window->setNoInputChannel(true);
2736 window->setFrame(Rect(0, 0, 200, 200));
2737
2738 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2739
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002740 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2742 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2743 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002744 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2745 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2748 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002749 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2750
2751 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2754 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002755 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2756
2757 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2759 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002761 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2762
2763 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2765 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2766 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002767 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2768 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002769 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2770 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2771 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002772 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2773
2774 // No more events
2775 spyWindow->assertNoEvents();
2776 window->assertNoEvents();
2777}
2778
2779/**
2780 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2781 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2782 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2783 * While the mouse is down, new move events from the touch device should be ignored.
2784 */
2785TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2787 sp<FakeWindowHandle> spyWindow =
2788 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2789 spyWindow->setFrame(Rect(0, 0, 200, 200));
2790 spyWindow->setTrustedOverlay(true);
2791 spyWindow->setSpy(true);
2792 sp<FakeWindowHandle> window =
2793 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2794 window->setFrame(Rect(0, 0, 200, 200));
2795
2796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2797
2798 const int32_t mouseDeviceId = 7;
2799 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002800
2801 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2803 .deviceId(mouseDeviceId)
2804 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2805 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002806 spyWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2808 window->consumeMotionEvent(
2809 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2810
2811 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2813 .deviceId(touchDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2815 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002816 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2817 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2818 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2819 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2820
Prabir Pradhan678438e2023-04-13 19:32:51 +00002821 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2822 .deviceId(touchDeviceId)
2823 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2824 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002825 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2826 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2827
2828 // Pilfer the stream
2829 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2830 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2831
Prabir Pradhan678438e2023-04-13 19:32:51 +00002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2835 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2837
2838 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2840 .deviceId(mouseDeviceId)
2841 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2842 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2843 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002844
2845 spyWindow->consumeMotionEvent(
2846 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2847 spyWindow->consumeMotionEvent(
2848 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2849 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2850
Prabir Pradhan678438e2023-04-13 19:32:51 +00002851 mDispatcher->notifyMotion(
2852 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2853 .deviceId(mouseDeviceId)
2854 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2855 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2856 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2857 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2859 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2860
2861 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2863 .deviceId(mouseDeviceId)
2864 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2865 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2866 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002867 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2868 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2869
2870 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2872 .deviceId(touchDeviceId)
2873 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2874 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002875
2876 // No more events
2877 spyWindow->assertNoEvents();
2878 window->assertNoEvents();
2879}
2880
2881/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002882 * On the display, have a single window, and also an area where there's no window.
2883 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2884 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2885 */
2886TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2887 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2888 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002889 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002890
2891 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002892
2893 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002894 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002895
2896 mDispatcher->waitForIdle();
2897 window->assertNoEvents();
2898
2899 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002900 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002901 mDispatcher->waitForIdle();
2902 window->consumeMotionDown();
2903}
2904
2905/**
2906 * Same test as above, but instead of touching the empty space, the first touch goes to
2907 * non-touchable window.
2908 */
2909TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2911 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002912 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002913 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2914 window1->setTouchable(false);
2915 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002916 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002917 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2918
2919 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2920
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002921 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002922 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002923
2924 mDispatcher->waitForIdle();
2925 window1->assertNoEvents();
2926 window2->assertNoEvents();
2927
2928 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002929 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002930 mDispatcher->waitForIdle();
2931 window2->consumeMotionDown();
2932}
2933
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002934/**
2935 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2936 * to the event time of the first ACTION_DOWN sent to the particular window.
2937 */
2938TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002941 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002942 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2943 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002944 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002945 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2946
2947 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2948
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002949 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002950 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002951
2952 mDispatcher->waitForIdle();
2953 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002954 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002955 window2->assertNoEvents();
2956 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2957 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2958 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2959
2960 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002962 mDispatcher->waitForIdle();
2963 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002964 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2966 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2967 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2968 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2969
2970 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002971 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002972 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002973 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002974
2975 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002976 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002978 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002979
2980 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2981 window1->consumeMotionMove();
2982 window1->assertNoEvents();
2983
2984 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002985 mDispatcher->notifyMotion(
2986 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002987 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002988 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002989
Prabir Pradhan678438e2023-04-13 19:32:51 +00002990 mDispatcher->notifyMotion(
2991 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002992 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002993 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002994}
2995
Garfield Tandf26e862020-07-01 20:18:19 -07002996TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002998 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002999 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003000 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003001 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003002 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003003 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003004
3005 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3006
3007 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3008
3009 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003011 injectMotionEvent(mDispatcher,
3012 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3013 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003014 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003015 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003016 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003017
3018 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003019 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003020 injectMotionEvent(mDispatcher,
3021 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3022 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003024 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003025 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3026 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003027
3028 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003030 injectMotionEvent(mDispatcher,
3031 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3032 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003034 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003035 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3036 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003037
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003039 injectMotionEvent(mDispatcher,
3040 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3041 AINPUT_SOURCE_MOUSE)
3042 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3043 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003045 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003046 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003047
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003049 injectMotionEvent(mDispatcher,
3050 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3051 AINPUT_SOURCE_MOUSE)
3052 .buttonState(0)
3053 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003055 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003056 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003057
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003059 injectMotionEvent(mDispatcher,
3060 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3061 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003062 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003063 .build()));
3064 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3065
3066 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003068 injectMotionEvent(mDispatcher,
3069 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3070 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003071 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003072 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003073 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003074
3075 // No more events
3076 windowLeft->assertNoEvents();
3077 windowRight->assertNoEvents();
3078}
3079
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003080/**
3081 * Put two fingers down (and don't release them) and click the mouse button.
3082 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3083 * currently active gesture should be canceled, and the new one should proceed.
3084 */
3085TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3087 sp<FakeWindowHandle> window =
3088 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3089 window->setFrame(Rect(0, 0, 600, 800));
3090
3091 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3092
3093 const int32_t touchDeviceId = 4;
3094 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003095
3096 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3098 .deviceId(touchDeviceId)
3099 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3100 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003101
Prabir Pradhan678438e2023-04-13 19:32:51 +00003102 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3103 .deviceId(touchDeviceId)
3104 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3105 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3106 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003107 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3108 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3109
3110 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3112 .deviceId(mouseDeviceId)
3113 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3114 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3115 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3117 WithPointerCount(2u)));
3118 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3119
Prabir Pradhan678438e2023-04-13 19:32:51 +00003120 mDispatcher->notifyMotion(
3121 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3122 .deviceId(mouseDeviceId)
3123 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3124 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3128
3129 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3130 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3132 .deviceId(touchDeviceId)
3133 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3134 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->assertNoEvents();
3137}
3138
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003139TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3141
3142 sp<FakeWindowHandle> spyWindow =
3143 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3144 spyWindow->setFrame(Rect(0, 0, 600, 800));
3145 spyWindow->setTrustedOverlay(true);
3146 spyWindow->setSpy(true);
3147 sp<FakeWindowHandle> window =
3148 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3149 window->setFrame(Rect(0, 0, 600, 800));
3150
3151 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3153
3154 // Send mouse cursor to the window
3155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3156 injectMotionEvent(mDispatcher,
3157 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3158 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003159 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003160 .x(100)
3161 .y(100))
3162 .build()));
3163
3164 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3165 WithSource(AINPUT_SOURCE_MOUSE)));
3166 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3167 WithSource(AINPUT_SOURCE_MOUSE)));
3168
3169 window->assertNoEvents();
3170 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003171}
3172
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003173TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3175
3176 sp<FakeWindowHandle> spyWindow =
3177 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3178 spyWindow->setFrame(Rect(0, 0, 600, 800));
3179 spyWindow->setTrustedOverlay(true);
3180 spyWindow->setSpy(true);
3181 sp<FakeWindowHandle> window =
3182 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3183 window->setFrame(Rect(0, 0, 600, 800));
3184
3185 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3187
3188 // Send mouse cursor to the window
3189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3190 injectMotionEvent(mDispatcher,
3191 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3192 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003193 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003194 .x(100)
3195 .y(100))
3196 .build()));
3197
3198 // Move mouse cursor
3199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3200 injectMotionEvent(mDispatcher,
3201 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3202 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003203 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003204 .x(110)
3205 .y(110))
3206 .build()));
3207
3208 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3209 WithSource(AINPUT_SOURCE_MOUSE)));
3210 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3211 WithSource(AINPUT_SOURCE_MOUSE)));
3212 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3213 WithSource(AINPUT_SOURCE_MOUSE)));
3214 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3215 WithSource(AINPUT_SOURCE_MOUSE)));
3216 // Touch down on the window
3217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3218 injectMotionEvent(mDispatcher,
3219 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3220 AINPUT_SOURCE_TOUCHSCREEN)
3221 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003222 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003223 .x(200)
3224 .y(200))
3225 .build()));
3226 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3227 WithSource(AINPUT_SOURCE_MOUSE)));
3228 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3229 WithSource(AINPUT_SOURCE_MOUSE)));
3230 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3231 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3232 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3233 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3234
3235 // pilfer the motion, retaining the gesture on the spy window.
3236 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3237 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3238 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3239
3240 // Touch UP on the window
3241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3242 injectMotionEvent(mDispatcher,
3243 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3244 AINPUT_SOURCE_TOUCHSCREEN)
3245 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003246 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003247 .x(200)
3248 .y(200))
3249 .build()));
3250 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3251 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3252
3253 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3254 // to send a new gesture. It should again go to both windows (spy and the window below), just
3255 // like the first gesture did, before pilfering. The window configuration has not changed.
3256
3257 // One more tap - DOWN
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3259 injectMotionEvent(mDispatcher,
3260 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3261 AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003263 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003264 .x(250)
3265 .y(250))
3266 .build()));
3267 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3268 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3269 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3270 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3271
3272 // Touch UP on the window
3273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3274 injectMotionEvent(mDispatcher,
3275 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3276 AINPUT_SOURCE_TOUCHSCREEN)
3277 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003278 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003279 .x(250)
3280 .y(250))
3281 .build()));
3282 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3283 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3284 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3285 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3286
3287 window->assertNoEvents();
3288 spyWindow->assertNoEvents();
3289}
3290
Garfield Tandf26e862020-07-01 20:18:19 -07003291// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3292// directly in this test.
3293TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003295 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003296 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003297 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003298
3299 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3300
3301 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3302
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003304 injectMotionEvent(mDispatcher,
3305 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3306 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003307 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003308 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003309 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003310 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003312 injectMotionEvent(mDispatcher,
3313 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3314 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003315 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003316 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3318 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003319
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003321 injectMotionEvent(mDispatcher,
3322 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3323 AINPUT_SOURCE_MOUSE)
3324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3325 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003327 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003328 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003329
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003331 injectMotionEvent(mDispatcher,
3332 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3333 AINPUT_SOURCE_MOUSE)
3334 .buttonState(0)
3335 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003336 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003337 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003338 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003339
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003341 injectMotionEvent(mDispatcher,
3342 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3343 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003344 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003345 .build()));
3346 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3347
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003348 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3349 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3350 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003351 injectMotionEvent(mDispatcher,
3352 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3353 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003354 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003355 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003356 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003357}
3358
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003359/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003360 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3361 * is generated.
3362 */
3363TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3365 sp<FakeWindowHandle> window =
3366 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3367 window->setFrame(Rect(0, 0, 1200, 800));
3368
3369 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3370
3371 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3372
3373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3374 injectMotionEvent(mDispatcher,
3375 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3376 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003377 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003378 .x(300)
3379 .y(400))
3380 .build()));
3381 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3382
3383 // Remove the window, but keep the channel.
3384 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3385 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3386}
3387
3388/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003389 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3390 */
3391TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3392 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3393 sp<FakeWindowHandle> window =
3394 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3395 window->setFrame(Rect(0, 0, 100, 100));
3396
3397 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3398
3399 const int32_t mouseDeviceId = 7;
3400 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003401
3402 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3404 .deviceId(mouseDeviceId)
3405 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3406 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003407 window->consumeMotionEvent(
3408 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3409
3410 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003411 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3412 .deviceId(touchDeviceId)
3413 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3414 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003415
3416 window->consumeMotionEvent(
3417 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3418 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3419}
3420
3421/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003422 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003423 * The tap causes a HOVER_EXIT event to be generated because the current event
3424 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003425 */
3426TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3428 sp<FakeWindowHandle> window =
3429 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3430 window->setFrame(Rect(0, 0, 100, 100));
3431
3432 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3433
3434 // Inject a hover_move from mouse.
3435 NotifyMotionArgs motionArgs =
3436 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3437 ADISPLAY_ID_DEFAULT, {{50, 50}});
3438 motionArgs.xCursorPosition = 50;
3439 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003440 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003441 ASSERT_NO_FATAL_FAILURE(
3442 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3443 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003444
3445 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3447 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3448 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003449 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003450 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3451 WithSource(AINPUT_SOURCE_MOUSE))));
3452
3453 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003454 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3455 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3456
Prabir Pradhan678438e2023-04-13 19:32:51 +00003457 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3458 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003459 ASSERT_NO_FATAL_FAILURE(
3460 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3461 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3462}
3463
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003464TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3466 sp<FakeWindowHandle> windowDefaultDisplay =
3467 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3468 ADISPLAY_ID_DEFAULT);
3469 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3470 sp<FakeWindowHandle> windowSecondDisplay =
3471 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3472 SECOND_DISPLAY_ID);
3473 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3474
3475 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3476 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3477
3478 // Set cursor position in window in default display and check that hover enter and move
3479 // events are generated.
3480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3481 injectMotionEvent(mDispatcher,
3482 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3483 AINPUT_SOURCE_MOUSE)
3484 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003485 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003486 .x(300)
3487 .y(600))
3488 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003489 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003490
3491 // Remove all windows in secondary display and check that no event happens on window in
3492 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003493 mDispatcher->setInputWindows(
3494 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003495 windowDefaultDisplay->assertNoEvents();
3496
3497 // Move cursor position in window in default display and check that only hover move
3498 // event is generated and not hover enter event.
3499 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3500 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3502 injectMotionEvent(mDispatcher,
3503 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3504 AINPUT_SOURCE_MOUSE)
3505 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003506 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003507 .x(400)
3508 .y(700))
3509 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003510 windowDefaultDisplay->consumeMotionEvent(
3511 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3512 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003513 windowDefaultDisplay->assertNoEvents();
3514}
3515
Garfield Tan00f511d2019-06-12 16:55:40 -07003516TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003518
3519 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003520 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003521 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003522 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003523 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003524 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003525
3526 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3527
Arthur Hung72d8dc32020-03-28 00:48:39 +00003528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003529
3530 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3531 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003533 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003534 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003535 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003536 windowRight->assertNoEvents();
3537}
3538
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003539TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003541 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3542 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003543 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003544
Arthur Hung72d8dc32020-03-28 00:48:39 +00003545 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003546 setFocusedWindow(window);
3547
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003548 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003549
Prabir Pradhan678438e2023-04-13 19:32:51 +00003550 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003551
3552 // Window should receive key down event.
3553 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3554
3555 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3556 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003557 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003558 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003559 AKEY_EVENT_FLAG_CANCELED);
3560}
3561
3562TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003564 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3565 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003566
Arthur Hung72d8dc32020-03-28 00:48:39 +00003567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003568
Prabir Pradhan678438e2023-04-13 19:32:51 +00003569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003571
3572 // Window should receive motion down event.
3573 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3574
3575 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3576 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003577 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003578 window->consumeMotionEvent(
3579 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003580}
3581
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003582TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3585 "Fake Window", ADISPLAY_ID_DEFAULT);
3586
3587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3588
3589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3591 .build());
3592
3593 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3594
3595 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3596 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3597 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3598
3599 // After the device has been reset, a new hovering stream can be sent to the window
3600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3601 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3602 .build());
3603 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3604}
3605
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003606TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003608 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3609 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003610 window->setFocusable(true);
3611
3612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3613 setFocusedWindow(window);
3614
3615 window->consumeFocusEvent(true);
3616
Prabir Pradhan678438e2023-04-13 19:32:51 +00003617 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003618 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3619 const nsecs_t injectTime = keyArgs.eventTime;
3620 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003622 // The dispatching time should be always greater than or equal to intercept key timeout.
3623 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3624 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3625 std::chrono::nanoseconds(interceptKeyTimeout).count());
3626}
3627
3628TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003630 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3631 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003632 window->setFocusable(true);
3633
3634 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3635 setFocusedWindow(window);
3636
3637 window->consumeFocusEvent(true);
3638
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003639 mFakePolicy->setInterceptKeyTimeout(150ms);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003640 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
3641 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003642
3643 // Window should receive key event immediately when same key up.
3644 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3645 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3646}
3647
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003648/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003649 * Two windows. First is a regular window. Second does not overlap with the first, and has
3650 * WATCH_OUTSIDE_TOUCH.
3651 * Both windows are owned by the same UID.
3652 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3653 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3654 */
3655TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3657 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3658 "First Window", ADISPLAY_ID_DEFAULT);
3659 window->setFrame(Rect{0, 0, 100, 100});
3660
3661 sp<FakeWindowHandle> outsideWindow =
3662 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3663 ADISPLAY_ID_DEFAULT);
3664 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3665 outsideWindow->setWatchOutsideTouch(true);
3666 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3668
3669 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003670 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3671 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3672 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003673 window->consumeMotionDown();
3674 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3675 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3676 outsideWindow->consumeMotionEvent(
3677 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3678}
3679
3680/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003681 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3682 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3683 * ACTION_OUTSIDE event is sent per gesture.
3684 */
3685TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3686 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3689 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003690 window->setWatchOutsideTouch(true);
3691 window->setFrame(Rect{0, 0, 100, 100});
3692 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003693 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3694 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003695 secondWindow->setFrame(Rect{100, 100, 200, 200});
3696 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003697 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3698 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003699 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3700 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3701
3702 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003703 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3704 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3705 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003706 window->assertNoEvents();
3707 secondWindow->assertNoEvents();
3708
3709 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3710 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003711 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3712 ADISPLAY_ID_DEFAULT,
3713 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003714 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3715 window->consumeMotionEvent(
3716 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003717 secondWindow->consumeMotionDown();
3718 thirdWindow->assertNoEvents();
3719
3720 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3721 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003722 mDispatcher->notifyMotion(
3723 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3724 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003725 window->assertNoEvents();
3726 secondWindow->consumeMotionMove();
3727 thirdWindow->consumeMotionDown();
3728}
3729
Prabir Pradhan814fe082022-07-22 20:22:18 +00003730TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3733 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003734 window->setFocusable(true);
3735
Patrick Williamsd828f302023-04-28 17:52:08 -05003736 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003737 setFocusedWindow(window);
3738
3739 window->consumeFocusEvent(true);
3740
Prabir Pradhan678438e2023-04-13 19:32:51 +00003741 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3742 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3743 mDispatcher->notifyKey(keyDown);
3744 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003745
3746 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3747 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3748
3749 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003750 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003751
3752 window->consumeFocusEvent(false);
3753
Prabir Pradhan678438e2023-04-13 19:32:51 +00003754 mDispatcher->notifyKey(keyDown);
3755 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003756 window->assertNoEvents();
3757}
3758
Arthur Hung96483742022-11-15 03:30:48 +00003759TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3762 "Fake Window", ADISPLAY_ID_DEFAULT);
3763 // Ensure window is non-split and have some transform.
3764 window->setPreventSplitting(true);
3765 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003767
3768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3769 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3770 {50, 50}))
3771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3772 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3773
3774 const MotionEvent secondFingerDownEvent =
3775 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3776 .displayId(ADISPLAY_ID_DEFAULT)
3777 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003778 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3779 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003780 .build();
3781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3782 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3783 InputEventInjectionSync::WAIT_FOR_RESULT))
3784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3785
3786 const MotionEvent* event = window->consumeMotion();
3787 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3788 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3789 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3790 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3791 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3792}
3793
Harry Cuttsb166c002023-05-09 13:06:05 +00003794TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3796 sp<FakeWindowHandle> window =
3797 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3798 window->setFrame(Rect(0, 0, 400, 400));
3799 sp<FakeWindowHandle> trustedOverlay =
3800 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3801 ADISPLAY_ID_DEFAULT);
3802 trustedOverlay->setSpy(true);
3803 trustedOverlay->setTrustedOverlay(true);
3804
3805 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3806
3807 // Start a three-finger touchpad swipe
3808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3809 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3810 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3811 .build());
3812 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3813 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3814 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3815 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3816 .build());
3817 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3818 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3819 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3820 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3821 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3822 .build());
3823
3824 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3825 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3826 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3827
3828 // Move the swipe a bit
3829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3830 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3831 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3832 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3833 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3834 .build());
3835
3836 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3837
3838 // End the swipe
3839 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3841 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3842 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3843 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3844 .build());
3845 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3846 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3847 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3848 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3849 .build());
3850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3851 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3852 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3853 .build());
3854
3855 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3856 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3857 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3858
3859 window->assertNoEvents();
3860}
3861
3862TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3863 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3864 sp<FakeWindowHandle> window =
3865 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3866 window->setFrame(Rect(0, 0, 400, 400));
3867 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3868
3869 // Start a three-finger touchpad swipe
3870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3872 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3873 .build());
3874 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3876 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3877 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3878 .build());
3879 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3880 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3881 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3882 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3883 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3884 .build());
3885
3886 // Move the swipe a bit
3887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3888 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3889 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3890 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3891 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3892 .build());
3893
3894 // End the swipe
3895 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3897 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3898 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3899 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3900 .build());
3901 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3902 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3903 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3904 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3905 .build());
3906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3907 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3909 .build());
3910
3911 window->assertNoEvents();
3912}
3913
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003914/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003915 * Ensure the correct coordinate spaces are used by InputDispatcher.
3916 *
3917 * InputDispatcher works in the display space, so its coordinate system is relative to the display
3918 * panel. Windows get events in the window space, and get raw coordinates in the logical display
3919 * space.
3920 */
3921class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
3922public:
3923 void SetUp() override {
3924 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003925 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003926 }
3927
3928 void addDisplayInfo(int displayId, const ui::Transform& transform) {
3929 gui::DisplayInfo info;
3930 info.displayId = displayId;
3931 info.transform = transform;
3932 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05003933 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003934 }
3935
3936 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
3937 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05003938 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003939 }
3940
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003941 void removeAllWindowsAndDisplays() {
3942 mDisplayInfos.clear();
3943 mWindowInfos.clear();
3944 }
3945
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003946 // Set up a test scenario where the display has a scaled projection and there are two windows
3947 // on the display.
3948 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
3949 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
3950 // respectively.
3951 ui::Transform displayTransform;
3952 displayTransform.set(2, 0, 0, 4);
3953 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
3954
3955 std::shared_ptr<FakeApplicationHandle> application =
3956 std::make_shared<FakeApplicationHandle>();
3957
3958 // Add two windows to the display. Their frames are represented in the display space.
3959 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003960 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
3961 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003962 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
3963 addWindow(firstWindow);
3964
3965 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003966 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3967 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003968 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
3969 addWindow(secondWindow);
3970 return {std::move(firstWindow), std::move(secondWindow)};
3971 }
3972
3973private:
3974 std::vector<gui::DisplayInfo> mDisplayInfos;
3975 std::vector<gui::WindowInfo> mWindowInfos;
3976};
3977
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003978TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003979 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3980 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00003981 // selected so that if the hit test was performed with the point and the bounds being in
3982 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003983 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3984 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3985 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003986
3987 firstWindow->consumeMotionDown();
3988 secondWindow->assertNoEvents();
3989}
3990
3991// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
3992// the event should be treated as being in the logical display space.
3993TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
3994 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
3995 // Send down to the first window. The point is represented in the logical display space. The
3996 // point is selected so that if the hit test was done in logical display space, then it would
3997 // end up in the incorrect window.
3998 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3999 PointF{75 * 2, 55 * 4});
4000
4001 firstWindow->consumeMotionDown();
4002 secondWindow->assertNoEvents();
4003}
4004
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004005// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4006// event should be treated as being in the logical display space.
4007TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4008 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4009
4010 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4011 ui::Transform injectedEventTransform;
4012 injectedEventTransform.set(matrix);
4013 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4014 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4015
4016 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4017 .displayId(ADISPLAY_ID_DEFAULT)
4018 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004019 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004020 .x(untransformedPoint.x)
4021 .y(untransformedPoint.y))
4022 .build();
4023 event.transform(matrix);
4024
4025 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4026 InputEventInjectionSync::WAIT_FOR_RESULT);
4027
4028 firstWindow->consumeMotionDown();
4029 secondWindow->assertNoEvents();
4030}
4031
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004032TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4033 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4034
4035 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004036 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4037 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4038 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004039
4040 firstWindow->assertNoEvents();
4041 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004042 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004043 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4044
4045 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4046 EXPECT_EQ(300, event->getRawX(0));
4047 EXPECT_EQ(880, event->getRawY(0));
4048
4049 // Ensure that the x and y values are in the window's coordinate space.
4050 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4051 // the logical display space. This will be the origin of the window space.
4052 EXPECT_EQ(100, event->getX(0));
4053 EXPECT_EQ(80, event->getY(0));
4054}
4055
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004056/** Ensure consistent behavior of InputDispatcher in all orientations. */
4057class InputDispatcherDisplayOrientationFixture
4058 : public InputDispatcherDisplayProjectionTest,
4059 public ::testing::WithParamInterface<ui::Rotation> {};
4060
4061// This test verifies the touchable region of a window for all rotations of the display by tapping
4062// in different locations on the display, specifically points close to the four corners of a
4063// window.
4064TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4065 constexpr static int32_t displayWidth = 400;
4066 constexpr static int32_t displayHeight = 800;
4067
4068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4069
4070 const auto rotation = GetParam();
4071
4072 // Set up the display with the specified rotation.
4073 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4074 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4075 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4076 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4077 logicalDisplayWidth, logicalDisplayHeight);
4078 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4079
4080 // Create a window with its bounds determined in the logical display.
4081 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4082 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4083 sp<FakeWindowHandle> window =
4084 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4085 window->setFrame(frameInDisplay, displayTransform);
4086 addWindow(window);
4087
4088 // The following points in logical display space should be inside the window.
4089 static const std::array<vec2, 4> insidePoints{
4090 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4091 for (const auto pointInsideWindow : insidePoints) {
4092 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4093 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004094 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4095 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4096 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004097 window->consumeMotionDown();
4098
Prabir Pradhan678438e2023-04-13 19:32:51 +00004099 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4100 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4101 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004102 window->consumeMotionUp();
4103 }
4104
4105 // The following points in logical display space should be outside the window.
4106 static const std::array<vec2, 5> outsidePoints{
4107 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4108 for (const auto pointOutsideWindow : outsidePoints) {
4109 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4110 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004111 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4113 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004114
Prabir Pradhan678438e2023-04-13 19:32:51 +00004115 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4116 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4117 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004118 }
4119 window->assertNoEvents();
4120}
4121
4122// Run the precision tests for all rotations.
4123INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4124 InputDispatcherDisplayOrientationFixture,
4125 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4126 ui::ROTATION_270),
4127 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4128 return ftl::enum_string(testParamInfo.param);
4129 });
4130
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004131using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4132 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004133
4134class TransferTouchFixture : public InputDispatcherTest,
4135 public ::testing::WithParamInterface<TransferFunction> {};
4136
4137TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004138 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004139
4140 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004141 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004142 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4143 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004144 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004145 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004146 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4147 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004148 sp<FakeWindowHandle> wallpaper =
4149 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4150 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004151 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004153
4154 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004155 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4156 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004157
Svet Ganov5d3bc372020-01-26 23:11:07 -08004158 // Only the first window should get the down event
4159 firstWindow->consumeMotionDown();
4160 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004161 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004162
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004163 // Transfer touch to the second window
4164 TransferFunction f = GetParam();
4165 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4166 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004167 // The first window gets cancel and the second gets down
4168 firstWindow->consumeMotionCancel();
4169 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004170 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004171
4172 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004173 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4174 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004175 // The first window gets no events and the second gets up
4176 firstWindow->assertNoEvents();
4177 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004178 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004179}
4180
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004181/**
4182 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4183 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4184 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4185 * natural to the user.
4186 * In this test, we are sending a pointer to both spy window and first window. We then try to
4187 * transfer touch to the second window. The dispatcher should identify the first window as the
4188 * one that should lose the gesture, and therefore the action should be to move the gesture from
4189 * the first window to the second.
4190 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4191 * the other API, as well.
4192 */
4193TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4195
4196 // Create a couple of windows + a spy window
4197 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004198 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004199 spyWindow->setTrustedOverlay(true);
4200 spyWindow->setSpy(true);
4201 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004202 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004203 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004204 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004205
4206 // Add the windows to the dispatcher
4207 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4208
4209 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004210 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4211 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004212 // Only the first window and spy should get the down event
4213 spyWindow->consumeMotionDown();
4214 firstWindow->consumeMotionDown();
4215
4216 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4217 // if f === 'transferTouch'.
4218 TransferFunction f = GetParam();
4219 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4220 ASSERT_TRUE(success);
4221 // The first window gets cancel and the second gets down
4222 firstWindow->consumeMotionCancel();
4223 secondWindow->consumeMotionDown();
4224
4225 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004226 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4227 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004228 // The first window gets no events and the second+spy get up
4229 firstWindow->assertNoEvents();
4230 spyWindow->consumeMotionUp();
4231 secondWindow->consumeMotionUp();
4232}
4233
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004234TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004235 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004236
4237 PointF touchPoint = {10, 10};
4238
4239 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004240 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004241 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4242 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004243 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004244 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004245 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4246 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004247 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004248
4249 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004250 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004251
4252 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004253 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4254 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4255 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004256 // Only the first window should get the down event
4257 firstWindow->consumeMotionDown();
4258 secondWindow->assertNoEvents();
4259
4260 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004261 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4262 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004263 // Only the first window should get the pointer down event
4264 firstWindow->consumeMotionPointerDown(1);
4265 secondWindow->assertNoEvents();
4266
4267 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004268 TransferFunction f = GetParam();
4269 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4270 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004271 // The first window gets cancel and the second gets down and pointer down
4272 firstWindow->consumeMotionCancel();
4273 secondWindow->consumeMotionDown();
4274 secondWindow->consumeMotionPointerDown(1);
4275
4276 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004277 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4278 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004279 // The first window gets nothing and the second gets pointer up
4280 firstWindow->assertNoEvents();
4281 secondWindow->consumeMotionPointerUp(1);
4282
4283 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004284 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4285 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004286 // The first window gets nothing and the second gets up
4287 firstWindow->assertNoEvents();
4288 secondWindow->consumeMotionUp();
4289}
4290
Arthur Hungc539dbb2022-12-08 07:45:36 +00004291TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4293
4294 // Create a couple of windows
4295 sp<FakeWindowHandle> firstWindow =
4296 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4297 ADISPLAY_ID_DEFAULT);
4298 firstWindow->setDupTouchToWallpaper(true);
4299 sp<FakeWindowHandle> secondWindow =
4300 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4301 ADISPLAY_ID_DEFAULT);
4302 secondWindow->setDupTouchToWallpaper(true);
4303
4304 sp<FakeWindowHandle> wallpaper1 =
4305 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4306 wallpaper1->setIsWallpaper(true);
4307
4308 sp<FakeWindowHandle> wallpaper2 =
4309 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4310 wallpaper2->setIsWallpaper(true);
4311 // Add the windows to the dispatcher
4312 mDispatcher->setInputWindows(
4313 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4314
4315 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004316 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4317 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004318
4319 // Only the first window should get the down event
4320 firstWindow->consumeMotionDown();
4321 secondWindow->assertNoEvents();
4322 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4323 wallpaper2->assertNoEvents();
4324
4325 // Transfer touch focus to the second window
4326 TransferFunction f = GetParam();
4327 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4328 ASSERT_TRUE(success);
4329
4330 // The first window gets cancel and the second gets down
4331 firstWindow->consumeMotionCancel();
4332 secondWindow->consumeMotionDown();
4333 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4334 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4335
4336 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004337 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4338 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004339 // The first window gets no events and the second gets up
4340 firstWindow->assertNoEvents();
4341 secondWindow->consumeMotionUp();
4342 wallpaper1->assertNoEvents();
4343 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4344}
4345
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004346// For the cases of single pointer touch and two pointers non-split touch, the api's
4347// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4348// for the case where there are multiple pointers split across several windows.
4349INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4350 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004351 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4352 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004353 return dispatcher->transferTouch(destChannelToken,
4354 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004355 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004356 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4357 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004358 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004359 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004360 }));
4361
Svet Ganov5d3bc372020-01-26 23:11:07 -08004362TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004364
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004365 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004366 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4367 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004368 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004369
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004370 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004371 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4372 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004373 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004374
4375 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004376 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004377
4378 PointF pointInFirst = {300, 200};
4379 PointF pointInSecond = {300, 600};
4380
4381 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004382 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4383 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4384 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004385 // Only the first window should get the down event
4386 firstWindow->consumeMotionDown();
4387 secondWindow->assertNoEvents();
4388
4389 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004390 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4391 ADISPLAY_ID_DEFAULT,
4392 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004393 // The first window gets a move and the second a down
4394 firstWindow->consumeMotionMove();
4395 secondWindow->consumeMotionDown();
4396
4397 // Transfer touch focus to the second window
4398 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4399 // The first window gets cancel and the new gets pointer down (it already saw down)
4400 firstWindow->consumeMotionCancel();
4401 secondWindow->consumeMotionPointerDown(1);
4402
4403 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004404 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4405 ADISPLAY_ID_DEFAULT,
4406 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004407 // The first window gets nothing and the second gets pointer up
4408 firstWindow->assertNoEvents();
4409 secondWindow->consumeMotionPointerUp(1);
4410
4411 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004412 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4413 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004414 // The first window gets nothing and the second gets up
4415 firstWindow->assertNoEvents();
4416 secondWindow->consumeMotionUp();
4417}
4418
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004419// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4420// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4421// touch is not supported, so the touch should continue on those windows and the transferred-to
4422// window should get nothing.
4423TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4425
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004426 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004427 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4428 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004429 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004430
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004431 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004432 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4433 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004434 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004435
4436 // Add the windows to the dispatcher
4437 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4438
4439 PointF pointInFirst = {300, 200};
4440 PointF pointInSecond = {300, 600};
4441
4442 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004443 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4444 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4445 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004446 // Only the first window should get the down event
4447 firstWindow->consumeMotionDown();
4448 secondWindow->assertNoEvents();
4449
4450 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004451 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4452 ADISPLAY_ID_DEFAULT,
4453 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004454 // The first window gets a move and the second a down
4455 firstWindow->consumeMotionMove();
4456 secondWindow->consumeMotionDown();
4457
4458 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004459 const bool transferred =
4460 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004461 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4462 ASSERT_FALSE(transferred);
4463 firstWindow->assertNoEvents();
4464 secondWindow->assertNoEvents();
4465
4466 // The rest of the dispatch should proceed as normal
4467 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004468 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4469 ADISPLAY_ID_DEFAULT,
4470 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004471 // The first window gets MOVE and the second gets pointer up
4472 firstWindow->consumeMotionMove();
4473 secondWindow->consumeMotionUp();
4474
4475 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004476 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4477 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004478 // The first window gets nothing and the second gets up
4479 firstWindow->consumeMotionUp();
4480 secondWindow->assertNoEvents();
4481}
4482
Arthur Hungabbb9d82021-09-01 14:52:30 +00004483// This case will create two windows and one mirrored window on the default display and mirror
4484// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4485// the windows info of second display before default display.
4486TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4487 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4488 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004489 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004490 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004491 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004492 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004493 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004494
4495 sp<FakeWindowHandle> mirrorWindowInPrimary =
4496 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4497 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004498
4499 sp<FakeWindowHandle> firstWindowInSecondary =
4500 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4501 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004502
4503 sp<FakeWindowHandle> secondWindowInSecondary =
4504 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4505 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004506
4507 // Update window info, let it find window handle of second display first.
4508 mDispatcher->setInputWindows(
4509 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4510 {ADISPLAY_ID_DEFAULT,
4511 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4512
4513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4514 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4515 {50, 50}))
4516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4517
4518 // Window should receive motion event.
4519 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4520
4521 // Transfer touch focus
4522 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4523 secondWindowInPrimary->getToken()));
4524 // The first window gets cancel.
4525 firstWindowInPrimary->consumeMotionCancel();
4526 secondWindowInPrimary->consumeMotionDown();
4527
4528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4529 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4530 ADISPLAY_ID_DEFAULT, {150, 50}))
4531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4532 firstWindowInPrimary->assertNoEvents();
4533 secondWindowInPrimary->consumeMotionMove();
4534
4535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4536 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4537 {150, 50}))
4538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4539 firstWindowInPrimary->assertNoEvents();
4540 secondWindowInPrimary->consumeMotionUp();
4541}
4542
4543// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4544// 'transferTouch' api.
4545TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4547 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004548 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004549 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004550 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004551 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004552 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004553
4554 sp<FakeWindowHandle> mirrorWindowInPrimary =
4555 firstWindowInPrimary->clone(application, mDispatcher, ADISPLAY_ID_DEFAULT);
4556 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004557
4558 sp<FakeWindowHandle> firstWindowInSecondary =
4559 firstWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4560 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004561
4562 sp<FakeWindowHandle> secondWindowInSecondary =
4563 secondWindowInPrimary->clone(application, mDispatcher, SECOND_DISPLAY_ID);
4564 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004565
4566 // Update window info, let it find window handle of second display first.
4567 mDispatcher->setInputWindows(
4568 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4569 {ADISPLAY_ID_DEFAULT,
4570 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4571
4572 // Touch on second display.
4573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4574 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4575 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4576
4577 // Window should receive motion event.
4578 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4579
4580 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004581 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582
4583 // The first window gets cancel.
4584 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4585 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4586
4587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4588 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4589 SECOND_DISPLAY_ID, {150, 50}))
4590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4591 firstWindowInPrimary->assertNoEvents();
4592 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4593
4594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4595 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4597 firstWindowInPrimary->assertNoEvents();
4598 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4599}
4600
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004601TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004603 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4604 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004605
Vishnu Nair47074b82020-08-14 11:54:47 -07004606 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004608 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004609
4610 window->consumeFocusEvent(true);
4611
Prabir Pradhan678438e2023-04-13 19:32:51 +00004612 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004613
4614 // Window should receive key down event.
4615 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004616
4617 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004618 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004619 mFakePolicy->assertUserActivityPoked();
4620}
4621
4622TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4624 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4625 "Fake Window", ADISPLAY_ID_DEFAULT);
4626
4627 window->setDisableUserActivity(true);
4628 window->setFocusable(true);
4629 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4630 setFocusedWindow(window);
4631
4632 window->consumeFocusEvent(true);
4633
4634 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4635
4636 // Window should receive key down event.
4637 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4638
4639 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004640 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004641 mFakePolicy->assertUserActivityNotPoked();
4642}
4643
4644TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4646 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4647 "Fake Window", ADISPLAY_ID_DEFAULT);
4648
4649 window->setFocusable(true);
4650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4651 setFocusedWindow(window);
4652
4653 window->consumeFocusEvent(true);
4654
4655 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4656 mDispatcher->waitForIdle();
4657
4658 // System key is not passed down
4659 window->assertNoEvents();
4660
4661 // Should have poked user activity
4662 mFakePolicy->assertUserActivityPoked();
4663}
4664
4665TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4667 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4668 "Fake Window", ADISPLAY_ID_DEFAULT);
4669
4670 window->setFocusable(true);
4671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4672 setFocusedWindow(window);
4673
4674 window->consumeFocusEvent(true);
4675
4676 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4677 mDispatcher->waitForIdle();
4678
4679 // System key is not passed down
4680 window->assertNoEvents();
4681
4682 // Should have poked user activity
4683 mFakePolicy->assertUserActivityPoked();
4684}
4685
4686TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4689 "Fake Window", ADISPLAY_ID_DEFAULT);
4690
4691 window->setDisableUserActivity(true);
4692 window->setFocusable(true);
4693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4694 setFocusedWindow(window);
4695
4696 window->consumeFocusEvent(true);
4697
4698 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4699 mDispatcher->waitForIdle();
4700
4701 // System key is not passed down
4702 window->assertNoEvents();
4703
4704 // Should have poked user activity
4705 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004706}
4707
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004708TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4711 "Fake Window", ADISPLAY_ID_DEFAULT);
4712
4713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4714
4715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4716 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4717 ADISPLAY_ID_DEFAULT, {100, 100}))
4718 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4719
4720 window->consumeMotionEvent(
4721 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4722
4723 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004724 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004725 mFakePolicy->assertUserActivityPoked();
4726}
4727
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004728TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004730 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4731 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004732
Arthur Hung72d8dc32020-03-28 00:48:39 +00004733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004734
Prabir Pradhan678438e2023-04-13 19:32:51 +00004735 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004736 mDispatcher->waitForIdle();
4737
4738 window->assertNoEvents();
4739}
4740
4741// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4742TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004743 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004744 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4745 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004746
Arthur Hung72d8dc32020-03-28 00:48:39 +00004747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004748
4749 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004750 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004751 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004752 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4753 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004754
4755 // Window should receive only the motion event
4756 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4757 window->assertNoEvents(); // Key event or focus event will not be received
4758}
4759
arthurhungea3f4fc2020-12-21 23:18:53 +08004760TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4762
arthurhungea3f4fc2020-12-21 23:18:53 +08004763 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004764 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4765 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004766 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004767
arthurhungea3f4fc2020-12-21 23:18:53 +08004768 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004769 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4770 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004771 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004772
4773 // Add the windows to the dispatcher
4774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4775
4776 PointF pointInFirst = {300, 200};
4777 PointF pointInSecond = {300, 600};
4778
4779 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004780 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4781 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4782 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004783 // Only the first window should get the down event
4784 firstWindow->consumeMotionDown();
4785 secondWindow->assertNoEvents();
4786
4787 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004788 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4789 ADISPLAY_ID_DEFAULT,
4790 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004791 // The first window gets a move and the second a down
4792 firstWindow->consumeMotionMove();
4793 secondWindow->consumeMotionDown();
4794
4795 // Send pointer cancel to the second window
4796 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004797 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004798 {pointInFirst, pointInSecond});
4799 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004800 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004801 // The first window gets move and the second gets cancel.
4802 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4803 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4804
4805 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004806 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4807 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004808 // The first window gets up and the second gets nothing.
4809 firstWindow->consumeMotionUp();
4810 secondWindow->assertNoEvents();
4811}
4812
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004813TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4815
4816 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004817 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4819 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4820 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4821 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4822
Harry Cutts33476232023-01-30 19:57:29 +00004823 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004824 window->assertNoEvents();
4825 mDispatcher->waitForIdle();
4826}
4827
chaviwd1c23182019-12-20 18:44:56 -08004828class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004829public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004830 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004831 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004832 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004833 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004834 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004835 }
4836
chaviwd1c23182019-12-20 18:44:56 -08004837 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4838
4839 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004840 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4841 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004842 }
4843
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004844 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4845
4846 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4847
chaviwd1c23182019-12-20 18:44:56 -08004848 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004849 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004850 expectedDisplayId, expectedFlags);
4851 }
4852
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004853 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004854 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004855 expectedDisplayId, expectedFlags);
4856 }
4857
chaviwd1c23182019-12-20 18:44:56 -08004858 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004859 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004860 expectedDisplayId, expectedFlags);
4861 }
4862
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004863 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004864 mInputReceiver->consumeMotionEvent(
4865 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4866 WithDisplayId(expectedDisplayId),
4867 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004868 }
4869
Arthur Hungfbfa5722021-11-16 02:45:54 +00004870 void consumeMotionPointerDown(int32_t pointerIdx) {
4871 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4872 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004873 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004874 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004875 }
4876
Evan Rosky84f07f02021-04-16 10:42:42 -07004877 MotionEvent* consumeMotion() {
4878 InputEvent* event = mInputReceiver->consume();
4879 if (!event) {
4880 ADD_FAILURE() << "No event was produced";
4881 return nullptr;
4882 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004883 if (event->getType() != InputEventType::MOTION) {
4884 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004885 return nullptr;
4886 }
4887 return static_cast<MotionEvent*>(event);
4888 }
4889
chaviwd1c23182019-12-20 18:44:56 -08004890 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4891
4892private:
4893 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004894};
4895
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004896using InputDispatcherMonitorTest = InputDispatcherTest;
4897
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004898/**
4899 * Two entities that receive touch: A window, and a global monitor.
4900 * The touch goes to the window, and then the window disappears.
4901 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4902 * for the monitor, as well.
4903 * 1. foregroundWindow
4904 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4905 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004906TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4908 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004909 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004910
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004911 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004912
4913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4915 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4916 {100, 200}))
4917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4918
4919 // Both the foreground window and the global monitor should receive the touch down
4920 window->consumeMotionDown();
4921 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
4922
4923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4924 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4925 ADISPLAY_ID_DEFAULT, {110, 200}))
4926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4927
4928 window->consumeMotionMove();
4929 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4930
4931 // Now the foreground window goes away
4932 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
4933 window->consumeMotionCancel();
4934 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
4935
4936 // If more events come in, there will be no more foreground window to send them to. This will
4937 // cause a cancel for the monitor, as well.
4938 ASSERT_EQ(InputEventInjectionResult::FAILED,
4939 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4940 ADISPLAY_ID_DEFAULT, {120, 200}))
4941 << "Injection should fail because the window was removed";
4942 window->assertNoEvents();
4943 // Global monitor now gets the cancel
4944 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
4945}
4946
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004947TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07004948 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004949 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4950 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004952
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004953 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004954
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004956 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00004958 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08004959 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004960}
4961
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004962TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
4963 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004964
Chris Yea209fde2020-07-22 13:54:51 -07004965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004966 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4967 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004968 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00004969
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004970 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00004971 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08004973 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004974 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004975
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004976 // Pilfer pointers from the monitor.
4977 // This should not do anything and the window should continue to receive events.
4978 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00004979
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004981 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4982 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004984
4985 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
4986 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00004987}
4988
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004989TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07004990 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004991 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4992 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4994 window->setWindowOffset(20, 40);
4995 window->setWindowTransform(0, 1, -1, 0);
4996
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004997 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07004998
4999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5000 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5002 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5003 MotionEvent* event = monitor.consumeMotion();
5004 // Even though window has transform, gesture monitor must not.
5005 ASSERT_EQ(ui::Transform(), event->getTransform());
5006}
5007
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005008TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005010 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005011
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005012 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005013 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005014 << "Injection should fail if there is a monitor, but no touchable window";
5015 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005016}
5017
chaviw81e2bb92019-12-18 15:03:51 -08005018TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005020 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5021 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005022
Arthur Hung72d8dc32020-03-28 00:48:39 +00005023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005024
5025 NotifyMotionArgs motionArgs =
5026 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5027 ADISPLAY_ID_DEFAULT);
5028
Prabir Pradhan678438e2023-04-13 19:32:51 +00005029 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005030 // Window should receive motion down event.
5031 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5032
5033 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005034 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005035 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5036 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5037 motionArgs.pointerCoords[0].getX() - 10);
5038
Prabir Pradhan678438e2023-04-13 19:32:51 +00005039 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005040 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005041 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005042}
5043
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005044/**
5045 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5046 * the device default right away. In the test scenario, we check both the default value,
5047 * and the action of enabling / disabling.
5048 */
5049TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5052 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005053 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005054
5055 // Set focused application.
5056 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005057 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005058
5059 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005060 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005061 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005062 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005063
5064 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005065 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005066 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005067 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005068
5069 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005070 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005071 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005072 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005073 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005074 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005075 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005076 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005077
5078 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005079 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005081 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005082
5083 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005084 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005085 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005086 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005087 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005088 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005089 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005090 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005091
5092 window->assertNoEvents();
5093}
5094
Gang Wange9087892020-01-07 12:17:14 -05005095TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005097 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5098 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005099
5100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005101 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005102
Arthur Hung72d8dc32020-03-28 00:48:39 +00005103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005104 setFocusedWindow(window);
5105
Harry Cutts33476232023-01-30 19:57:29 +00005106 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005107
Prabir Pradhan678438e2023-04-13 19:32:51 +00005108 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5109 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005110
5111 InputEvent* event = window->consume();
5112 ASSERT_NE(event, nullptr);
5113
5114 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5115 ASSERT_NE(verified, nullptr);
5116 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5117
5118 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5119 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5120 ASSERT_EQ(keyArgs.source, verified->source);
5121 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5122
5123 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5124
5125 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005126 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005127 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005128 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5129 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5130 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5131 ASSERT_EQ(0, verifiedKey.repeatCount);
5132}
5133
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005134TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005135 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005136 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5137 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005138
5139 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5140
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005141 ui::Transform transform;
5142 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5143
5144 gui::DisplayInfo displayInfo;
5145 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5146 displayInfo.transform = transform;
5147
Patrick Williamsd828f302023-04-28 17:52:08 -05005148 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005149
Prabir Pradhan678438e2023-04-13 19:32:51 +00005150 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005151 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5152 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005153 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005154
5155 InputEvent* event = window->consume();
5156 ASSERT_NE(event, nullptr);
5157
5158 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5159 ASSERT_NE(verified, nullptr);
5160 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5161
5162 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5163 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5164 EXPECT_EQ(motionArgs.source, verified->source);
5165 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5166
5167 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5168
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005169 const vec2 rawXY =
5170 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5171 motionArgs.pointerCoords[0].getXYValue());
5172 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5173 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005174 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005175 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005176 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005177 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5178 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5179}
5180
chaviw09c8d2d2020-08-24 15:48:26 -07005181/**
5182 * Ensure that separate calls to sign the same data are generating the same key.
5183 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5184 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5185 * tests.
5186 */
5187TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5188 KeyEvent event = getTestKeyEvent();
5189 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5190
5191 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5192 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5193 ASSERT_EQ(hmac1, hmac2);
5194}
5195
5196/**
5197 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5198 */
5199TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5200 KeyEvent event = getTestKeyEvent();
5201 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5202 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5203
5204 verifiedEvent.deviceId += 1;
5205 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5206
5207 verifiedEvent.source += 1;
5208 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5209
5210 verifiedEvent.eventTimeNanos += 1;
5211 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5212
5213 verifiedEvent.displayId += 1;
5214 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5215
5216 verifiedEvent.action += 1;
5217 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5218
5219 verifiedEvent.downTimeNanos += 1;
5220 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5221
5222 verifiedEvent.flags += 1;
5223 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5224
5225 verifiedEvent.keyCode += 1;
5226 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5227
5228 verifiedEvent.scanCode += 1;
5229 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5230
5231 verifiedEvent.metaState += 1;
5232 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5233
5234 verifiedEvent.repeatCount += 1;
5235 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5236}
5237
Vishnu Nair958da932020-08-21 17:12:37 -07005238TEST_F(InputDispatcherTest, SetFocusedWindow) {
5239 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5240 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005241 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005242 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005243 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005244 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5245
5246 // Top window is also focusable but is not granted focus.
5247 windowTop->setFocusable(true);
5248 windowSecond->setFocusable(true);
5249 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5250 setFocusedWindow(windowSecond);
5251
5252 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5254 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005255
5256 // Focused window should receive event.
5257 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5258 windowTop->assertNoEvents();
5259}
5260
5261TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5262 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5263 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005264 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005265 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5266
5267 window->setFocusable(true);
5268 // Release channel for window is no longer valid.
5269 window->releaseChannel();
5270 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5271 setFocusedWindow(window);
5272
5273 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005274 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5275 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005276
5277 // window channel is invalid, so it should not receive any input event.
5278 window->assertNoEvents();
5279}
5280
5281TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5283 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005284 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005285 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005286 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5287
Vishnu Nair958da932020-08-21 17:12:37 -07005288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5289 setFocusedWindow(window);
5290
5291 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005292 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5293 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005294
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005295 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005296 window->assertNoEvents();
5297}
5298
5299TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5301 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005302 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005303 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005304 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005305 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5306
5307 windowTop->setFocusable(true);
5308 windowSecond->setFocusable(true);
5309 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5310 setFocusedWindow(windowTop);
5311 windowTop->consumeFocusEvent(true);
5312
Chavi Weingarten847e8512023-03-29 00:26:09 +00005313 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5314 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005315 windowSecond->consumeFocusEvent(true);
5316 windowTop->consumeFocusEvent(false);
5317
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5319 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005320
5321 // Focused window should receive event.
5322 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5323}
5324
Chavi Weingarten847e8512023-03-29 00:26:09 +00005325TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5327 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005328 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005329 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005330 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5332
5333 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005334 windowSecond->setFocusable(false);
5335 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005337 setFocusedWindow(windowTop);
5338 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005339
Chavi Weingarten847e8512023-03-29 00:26:09 +00005340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5341 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005342
5343 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005344 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005345 windowSecond->assertNoEvents();
5346}
5347
5348TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5350 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005351 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005352 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005353 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5354 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5356
5357 window->setFocusable(true);
5358 previousFocusedWindow->setFocusable(true);
5359 window->setVisible(false);
5360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5361 setFocusedWindow(previousFocusedWindow);
5362 previousFocusedWindow->consumeFocusEvent(true);
5363
5364 // Requesting focus on invisible window takes focus from currently focused window.
5365 setFocusedWindow(window);
5366 previousFocusedWindow->consumeFocusEvent(false);
5367
5368 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005370 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5371 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005372
5373 // Window does not get focus event or key down.
5374 window->assertNoEvents();
5375
5376 // Window becomes visible.
5377 window->setVisible(true);
5378 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5379
5380 // Window receives focus event.
5381 window->consumeFocusEvent(true);
5382 // Focused window receives key down.
5383 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5384}
5385
Vishnu Nair599f1412021-06-21 10:39:58 -07005386TEST_F(InputDispatcherTest, DisplayRemoved) {
5387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5388 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005390 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5391
5392 // window is granted focus.
5393 window->setFocusable(true);
5394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5395 setFocusedWindow(window);
5396 window->consumeFocusEvent(true);
5397
5398 // When a display is removed window loses focus.
5399 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5400 window->consumeFocusEvent(false);
5401}
5402
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005403/**
5404 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5405 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5406 * of the 'slipperyEnterWindow'.
5407 *
5408 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5409 * a way so that the touched location is no longer covered by the top window.
5410 *
5411 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5412 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5413 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5414 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5415 * with ACTION_DOWN).
5416 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5417 * window moved itself away from the touched location and had Flag::SLIPPERY.
5418 *
5419 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5420 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5421 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5422 *
5423 * In this test, we ensure that the event received by the bottom window has
5424 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5425 */
5426TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00005427 constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
5428 constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005429
5430 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5431 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5432
5433 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005434 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005435 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005436 // Make sure this one overlaps the bottom window
5437 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5438 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5439 // one. Windows with the same owner are not considered to be occluding each other.
5440 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5441
5442 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005443 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005444 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5445
5446 mDispatcher->setInputWindows(
5447 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5448
5449 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005450 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5451 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5452 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005453 slipperyExitWindow->consumeMotionDown();
5454 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5455 mDispatcher->setInputWindows(
5456 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5457
Prabir Pradhan678438e2023-04-13 19:32:51 +00005458 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5459 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5460 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005461
5462 slipperyExitWindow->consumeMotionCancel();
5463
5464 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5465 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5466}
5467
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005468/**
5469 * Two windows, one on the left and another on the right. The left window is slippery. The right
5470 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5471 * touch moves from the left window into the right window, the gesture should continue to go to the
5472 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5473 * reproduces a crash.
5474 */
5475TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5477
5478 sp<FakeWindowHandle> leftSlipperyWindow =
5479 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5480 leftSlipperyWindow->setSlippery(true);
5481 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5482
5483 sp<FakeWindowHandle> rightDropTouchesWindow =
5484 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5485 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5486 rightDropTouchesWindow->setDropInput(true);
5487
5488 mDispatcher->setInputWindows(
5489 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5490
5491 // Start touch in the left window
5492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5493 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5494 .build());
5495 leftSlipperyWindow->consumeMotionDown();
5496
5497 // And move it into the right window
5498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5499 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5500 .build());
5501
5502 // Since the right window isn't eligible to receive input, touch does not slip.
5503 // The left window continues to receive the gesture.
5504 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5505 rightDropTouchesWindow->assertNoEvents();
5506}
5507
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005508TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
5509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5510
5511 sp<FakeWindowHandle> leftWindow =
5512 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5513 leftWindow->setFrame(Rect(0, 0, 100, 100));
5514 leftWindow->setOwnerInfo(1, 101);
5515
5516 sp<FakeWindowHandle> rightSpy =
5517 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5518 rightSpy->setFrame(Rect(100, 0, 200, 100));
5519 rightSpy->setOwnerInfo(2, 102);
5520 rightSpy->setSpy(true);
5521 rightSpy->setTrustedOverlay(true);
5522
5523 sp<FakeWindowHandle> rightWindow =
5524 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5525 rightWindow->setFrame(Rect(100, 0, 200, 100));
5526 rightWindow->setOwnerInfo(3, 103);
5527
5528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5529
5530 // Touch in the left window
5531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5532 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5533 .build());
5534 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5535 mDispatcher->waitForIdle();
5536 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5537
5538 // Touch another finger over the right windows
5539 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5540 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5541 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5542 .build());
5543 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5544 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5545 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5546 mDispatcher->waitForIdle();
5547 ASSERT_NO_FATAL_FAILURE(
5548 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101, 102, 103}));
5549
5550 // Release finger over left window. The UP actions are not treated as device interaction.
5551 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5552 // is part of the UP action, we do not treat this as device interaction.
5553 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5554 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5555 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5556 .build());
5557 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5558 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5559 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5560 mDispatcher->waitForIdle();
5561 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5562
5563 // Move remaining finger
5564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5565 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5566 .build());
5567 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5568 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5569 mDispatcher->waitForIdle();
5570 ASSERT_NO_FATAL_FAILURE(
5571 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {102, 103}));
5572
5573 // Release all fingers
5574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5575 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5576 .build());
5577 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5578 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5579 mDispatcher->waitForIdle();
5580 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5581}
5582
5583TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5585
5586 sp<FakeWindowHandle> window =
5587 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5588 window->setFrame(Rect(0, 0, 100, 100));
5589 window->setOwnerInfo(1, 101);
5590
5591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5592 setFocusedWindow(window);
5593 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5594
5595 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5596 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5597 mDispatcher->waitForIdle();
5598 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {101}));
5599
5600 // The UP actions are not treated as device interaction.
5601 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5602 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5603 mDispatcher->waitForIdle();
5604 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5605}
5606
Garfield Tan1c7bc862020-01-28 13:24:04 -08005607class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5608protected:
5609 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5610 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5611
Chris Yea209fde2020-07-22 13:54:51 -07005612 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005613 sp<FakeWindowHandle> mWindow;
5614
5615 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005616 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005617 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005618 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005619 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005620 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5621 ASSERT_EQ(OK, mDispatcher->start());
5622
5623 setUpWindow();
5624 }
5625
5626 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005627 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005628 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005629
Vishnu Nair47074b82020-08-14 11:54:47 -07005630 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005631 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005632 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005633 mWindow->consumeFocusEvent(true);
5634 }
5635
Chris Ye2ad95392020-09-01 13:44:44 -07005636 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005637 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005638 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005639 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005640 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005641
5642 // Window should receive key down event.
5643 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5644 }
5645
5646 void expectKeyRepeatOnce(int32_t repeatCount) {
5647 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5648 InputEvent* repeatEvent = mWindow->consume();
5649 ASSERT_NE(nullptr, repeatEvent);
5650
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005651 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005652
5653 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5654 uint32_t eventAction = repeatKeyEvent->getAction();
5655 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5656 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5657 }
5658
Chris Ye2ad95392020-09-01 13:44:44 -07005659 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005660 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005661 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005662 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005663 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005664
5665 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005666 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005667 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005668 }
5669};
5670
5671TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005672 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005673 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5674 expectKeyRepeatOnce(repeatCount);
5675 }
5676}
5677
5678TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005679 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005680 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5681 expectKeyRepeatOnce(repeatCount);
5682 }
Harry Cutts33476232023-01-30 19:57:29 +00005683 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005684 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005685 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5686 expectKeyRepeatOnce(repeatCount);
5687 }
5688}
5689
5690TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005691 sendAndConsumeKeyDown(/*deviceId=*/1);
5692 expectKeyRepeatOnce(/*repeatCount=*/1);
5693 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005694 mWindow->assertNoEvents();
5695}
5696
5697TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005698 sendAndConsumeKeyDown(/*deviceId=*/1);
5699 expectKeyRepeatOnce(/*repeatCount=*/1);
5700 sendAndConsumeKeyDown(/*deviceId=*/2);
5701 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005702 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005703 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005704 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005705 expectKeyRepeatOnce(/*repeatCount=*/2);
5706 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005707 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005708 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005709 mWindow->assertNoEvents();
5710}
5711
5712TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005713 sendAndConsumeKeyDown(/*deviceId=*/1);
5714 expectKeyRepeatOnce(/*repeatCount=*/1);
5715 sendAndConsumeKeyDown(/*deviceId=*/2);
5716 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005717 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005718 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005719 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005720 mWindow->assertNoEvents();
5721}
5722
liushenxiang42232912021-05-21 20:24:09 +08005723TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5724 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005725 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005726 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005727 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5728 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5729 mWindow->assertNoEvents();
5730}
5731
Garfield Tan1c7bc862020-01-28 13:24:04 -08005732TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005733 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005734 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005735 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5736 InputEvent* repeatEvent = mWindow->consume();
5737 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5738 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5739 IdGenerator::getSource(repeatEvent->getId()));
5740 }
5741}
5742
5743TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005744 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005745 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005746
5747 std::unordered_set<int32_t> idSet;
5748 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5749 InputEvent* repeatEvent = mWindow->consume();
5750 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5751 int32_t id = repeatEvent->getId();
5752 EXPECT_EQ(idSet.end(), idSet.find(id));
5753 idSet.insert(id);
5754 }
5755}
5756
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005757/* Test InputDispatcher for MultiDisplay */
5758class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5759public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005760 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005761 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005762
Chris Yea209fde2020-07-22 13:54:51 -07005763 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005764 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005765 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005766
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005767 // Set focus window for primary display, but focused display would be second one.
5768 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005769 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005771 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005772 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005773
Chris Yea209fde2020-07-22 13:54:51 -07005774 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005775 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005776 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005777 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005778 // Set focus display to second one.
5779 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5780 // Set focus window for second display.
5781 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005782 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005783 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005784 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005785 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005786 }
5787
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005788 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005789 InputDispatcherTest::TearDown();
5790
Chris Yea209fde2020-07-22 13:54:51 -07005791 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005792 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005793 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005794 windowInSecondary.clear();
5795 }
5796
5797protected:
Chris Yea209fde2020-07-22 13:54:51 -07005798 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005799 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005800 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005801 sp<FakeWindowHandle> windowInSecondary;
5802};
5803
5804TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5805 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5807 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005809 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005810 windowInSecondary->assertNoEvents();
5811
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005812 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5814 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005816 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005817 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005818}
5819
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005820TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005821 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5823 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005824 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005825 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005826 windowInSecondary->assertNoEvents();
5827
5828 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005830 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005831 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005832 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005833
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005834 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005835 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005836
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005837 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005838 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005839 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005840
5841 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005842 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005843 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005844 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005845 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005846 windowInSecondary->assertNoEvents();
5847}
5848
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005849// Test per-display input monitors for motion event.
5850TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005851 FakeMonitorReceiver monitorInPrimary =
5852 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5853 FakeMonitorReceiver monitorInSecondary =
5854 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005855
5856 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5858 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005860 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005861 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005862 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005863 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005864
5865 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5867 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5868 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005869 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005870 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005871 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005872 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005873
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005874 // Lift up the touch from the second display
5875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5876 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5878 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5879 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5880
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005881 // Test inject a non-pointer motion event.
5882 // If specific a display, it will dispatch to the focused window of particular display,
5883 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5885 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005887 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005888 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005889 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005890 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005891}
5892
5893// Test per-display input monitors for key event.
5894TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005895 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005896 FakeMonitorReceiver monitorInPrimary =
5897 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5898 FakeMonitorReceiver monitorInSecondary =
5899 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005900
5901 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5903 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005904 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005905 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005906 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005907 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005908}
5909
Vishnu Nair958da932020-08-21 17:12:37 -07005910TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5911 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005912 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005913 secondWindowInPrimary->setFocusable(true);
5914 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5915 setFocusedWindow(secondWindowInPrimary);
5916 windowInPrimary->consumeFocusEvent(false);
5917 secondWindowInPrimary->consumeFocusEvent(true);
5918
5919 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
5921 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005922 windowInPrimary->assertNoEvents();
5923 windowInSecondary->assertNoEvents();
5924 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5925}
5926
Arthur Hungdfd528e2021-12-08 13:23:04 +00005927TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
5928 FakeMonitorReceiver monitorInPrimary =
5929 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5930 FakeMonitorReceiver monitorInSecondary =
5931 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
5932
5933 // Test touch down on primary display.
5934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5935 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5936 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5937 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5938 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5939
5940 // Test touch down on second display.
5941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5942 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5944 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
5945 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
5946
5947 // Trigger cancel touch.
5948 mDispatcher->cancelCurrentTouch();
5949 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5950 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5951 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5952 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
5953
5954 // Test inject a move motion event, no window/monitor should receive the event.
5955 ASSERT_EQ(InputEventInjectionResult::FAILED,
5956 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5957 ADISPLAY_ID_DEFAULT, {110, 200}))
5958 << "Inject motion event should return InputEventInjectionResult::FAILED";
5959 windowInPrimary->assertNoEvents();
5960 monitorInPrimary.assertNoEvents();
5961
5962 ASSERT_EQ(InputEventInjectionResult::FAILED,
5963 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5964 SECOND_DISPLAY_ID, {110, 200}))
5965 << "Inject motion event should return InputEventInjectionResult::FAILED";
5966 windowInSecondary->assertNoEvents();
5967 monitorInSecondary.assertNoEvents();
5968}
5969
Jackal Guof9696682018-10-05 12:23:23 +08005970class InputFilterTest : public InputDispatcherTest {
5971protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005972 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
5973 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08005974 NotifyMotionArgs motionArgs;
5975
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005976 motionArgs =
5977 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005978 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005979 motionArgs =
5980 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005981 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005982 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005983 if (expectToBeFiltered) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -07005984 const auto xy = transform.transform(motionArgs.pointerCoords->getXYValue());
5985 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08005986 } else {
5987 mFakePolicy->assertFilterInputEventWasNotCalled();
5988 }
5989 }
5990
5991 void testNotifyKey(bool expectToBeFiltered) {
5992 NotifyKeyArgs keyArgs;
5993
5994 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005995 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08005996 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005997 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005998 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08005999
6000 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006001 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006002 } else {
6003 mFakePolicy->assertFilterInputEventWasNotCalled();
6004 }
6005 }
6006};
6007
6008// Test InputFilter for MotionEvent
6009TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6010 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6011 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6012 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6013
6014 // Enable InputFilter
6015 mDispatcher->setInputFilterEnabled(true);
6016 // Test touch on both primary and second display, and check if both events are filtered.
6017 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6018 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6019
6020 // Disable InputFilter
6021 mDispatcher->setInputFilterEnabled(false);
6022 // Test touch on both primary and second display, and check if both events aren't filtered.
6023 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6024 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6025}
6026
6027// Test InputFilter for KeyEvent
6028TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6029 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6030 testNotifyKey(/*expectToBeFiltered*/ false);
6031
6032 // Enable InputFilter
6033 mDispatcher->setInputFilterEnabled(true);
6034 // Send a key event, and check if it is filtered.
6035 testNotifyKey(/*expectToBeFiltered*/ true);
6036
6037 // Disable InputFilter
6038 mDispatcher->setInputFilterEnabled(false);
6039 // Send a key event, and check if it isn't filtered.
6040 testNotifyKey(/*expectToBeFiltered*/ false);
6041}
6042
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006043// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6044// logical display coordinate space.
6045TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6046 ui::Transform firstDisplayTransform;
6047 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6048 ui::Transform secondDisplayTransform;
6049 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6050
6051 std::vector<gui::DisplayInfo> displayInfos(2);
6052 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6053 displayInfos[0].transform = firstDisplayTransform;
6054 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6055 displayInfos[1].transform = secondDisplayTransform;
6056
Patrick Williamsd828f302023-04-28 17:52:08 -05006057 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006058
6059 // Enable InputFilter
6060 mDispatcher->setInputFilterEnabled(true);
6061
6062 // Ensure the correct transforms are used for the displays.
6063 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6064 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6065}
6066
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006067class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6068protected:
6069 virtual void SetUp() override {
6070 InputDispatcherTest::SetUp();
6071
6072 /**
6073 * We don't need to enable input filter to test the injected event policy, but we enabled it
6074 * here to make the tests more realistic, since this policy only matters when inputfilter is
6075 * on.
6076 */
6077 mDispatcher->setInputFilterEnabled(true);
6078
6079 std::shared_ptr<InputApplicationHandle> application =
6080 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006081 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6082 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006083
6084 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6085 mWindow->setFocusable(true);
6086 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6087 setFocusedWindow(mWindow);
6088 mWindow->consumeFocusEvent(true);
6089 }
6090
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006091 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6092 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006093 KeyEvent event;
6094
6095 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6096 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6097 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006098 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006099 const int32_t additionalPolicyFlags =
6100 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006102 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006103 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6104 policyFlags | additionalPolicyFlags));
6105
6106 InputEvent* received = mWindow->consume();
6107 ASSERT_NE(nullptr, received);
6108 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006109 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006110 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6111 ASSERT_EQ(flags, keyEvent.getFlags());
6112 }
6113
6114 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6115 int32_t flags) {
6116 MotionEvent event;
6117 PointerProperties pointerProperties[1];
6118 PointerCoords pointerCoords[1];
6119 pointerProperties[0].clear();
6120 pointerProperties[0].id = 0;
6121 pointerCoords[0].clear();
6122 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6123 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6124
6125 ui::Transform identityTransform;
6126 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6127 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6128 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6129 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6130 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006131 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006132 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006133 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6134
6135 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006137 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006138 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6139 policyFlags | additionalPolicyFlags));
6140
6141 InputEvent* received = mWindow->consume();
6142 ASSERT_NE(nullptr, received);
6143 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006144 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006145 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6146 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006147 }
6148
6149private:
6150 sp<FakeWindowHandle> mWindow;
6151};
6152
6153TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006154 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6155 // filter. Without it, the event will no different from a regularly injected event, and the
6156 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006157 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6158 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006159}
6160
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006161TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006162 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006163 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006164 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6165}
6166
6167TEST_F(InputFilterInjectionPolicyTest,
6168 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6169 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006170 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006171 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006172}
6173
6174TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006175 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6176 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006177}
6178
chaviwfd6d3512019-03-25 13:23:49 -07006179class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006180 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006181 InputDispatcherTest::SetUp();
6182
Chris Yea209fde2020-07-22 13:54:51 -07006183 std::shared_ptr<FakeApplicationHandle> application =
6184 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006185 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006186 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006187 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006188
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006189 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006190 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006191 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006192
6193 // Set focused application.
6194 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006195 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006196
6197 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006199 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006200 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006201 }
6202
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006203 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006204 InputDispatcherTest::TearDown();
6205
6206 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006207 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006208 }
6209
6210protected:
6211 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006212 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006213 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006214};
6215
6216// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6217// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6218// the onPointerDownOutsideFocus callback.
6219TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006221 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6222 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006223 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006224 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006225
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006226 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006227 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6228}
6229
6230// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6231// DOWN on the window that doesn't have focus. Ensure no window received the
6232// onPointerDownOutsideFocus callback.
6233TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006235 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006237 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006238
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006239 ASSERT_TRUE(mDispatcher->waitForIdle());
6240 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006241}
6242
6243// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6244// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6245TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6247 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006248 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006249 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006250
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006251 ASSERT_TRUE(mDispatcher->waitForIdle());
6252 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006253}
6254
6255// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6256// DOWN on the window that already has focus. Ensure no window received the
6257// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006258TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006260 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006261 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006263 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006264
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006265 ASSERT_TRUE(mDispatcher->waitForIdle());
6266 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006267}
6268
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006269// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6270// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6271TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6272 const MotionEvent event =
6273 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6274 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006275 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006276 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6277 .build();
6278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6279 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6280 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6281
6282 ASSERT_TRUE(mDispatcher->waitForIdle());
6283 mFakePolicy->assertOnPointerDownWasNotCalled();
6284 // Ensure that the unfocused window did not receive any FOCUS events.
6285 mUnfocusedWindow->assertNoEvents();
6286}
6287
chaviwaf87b3e2019-10-01 16:59:28 -07006288// These tests ensures we can send touch events to a single client when there are multiple input
6289// windows that point to the same client token.
6290class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6291 virtual void SetUp() override {
6292 InputDispatcherTest::SetUp();
6293
Chris Yea209fde2020-07-22 13:54:51 -07006294 std::shared_ptr<FakeApplicationHandle> application =
6295 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006296 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6297 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006298 mWindow1->setFrame(Rect(0, 0, 100, 100));
6299
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006300 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6301 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006302 mWindow2->setFrame(Rect(100, 100, 200, 200));
6303
Arthur Hung72d8dc32020-03-28 00:48:39 +00006304 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006305 }
6306
6307protected:
6308 sp<FakeWindowHandle> mWindow1;
6309 sp<FakeWindowHandle> mWindow2;
6310
6311 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006312 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006313 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6314 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006315 }
6316
6317 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6318 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006319 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006320 InputEvent* event = window->consume();
6321
6322 ASSERT_NE(nullptr, event) << name.c_str()
6323 << ": consumer should have returned non-NULL event.";
6324
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006325 ASSERT_EQ(InputEventType::MOTION, event->getType())
6326 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006327
6328 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006329 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006330 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006331
6332 for (size_t i = 0; i < points.size(); i++) {
6333 float expectedX = points[i].x;
6334 float expectedY = points[i].y;
6335
6336 EXPECT_EQ(expectedX, motionEvent.getX(i))
6337 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6338 << ", got " << motionEvent.getX(i);
6339 EXPECT_EQ(expectedY, motionEvent.getY(i))
6340 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6341 << ", got " << motionEvent.getY(i);
6342 }
6343 }
chaviw9eaa22c2020-07-01 16:21:27 -07006344
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006345 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006346 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006347 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6348 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006349
6350 // Always consume from window1 since it's the window that has the InputReceiver
6351 consumeMotionEvent(mWindow1, action, expectedPoints);
6352 }
chaviwaf87b3e2019-10-01 16:59:28 -07006353};
6354
6355TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6356 // Touch Window 1
6357 PointF touchedPoint = {10, 10};
6358 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006359 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006360
6361 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006362 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006363
6364 // Touch Window 2
6365 touchedPoint = {150, 150};
6366 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006367 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006368}
6369
chaviw9eaa22c2020-07-01 16:21:27 -07006370TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6371 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006372 mWindow2->setWindowScale(0.5f, 0.5f);
6373
6374 // Touch Window 1
6375 PointF touchedPoint = {10, 10};
6376 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006377 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006378 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006379 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006380
6381 // Touch Window 2
6382 touchedPoint = {150, 150};
6383 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006384 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6385 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006386
chaviw9eaa22c2020-07-01 16:21:27 -07006387 // Update the transform so rotation is set
6388 mWindow2->setWindowTransform(0, -1, 1, 0);
6389 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6390 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006391}
6392
chaviw9eaa22c2020-07-01 16:21:27 -07006393TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006394 mWindow2->setWindowScale(0.5f, 0.5f);
6395
6396 // Touch Window 1
6397 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6398 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006399 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006400
6401 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006402 touchedPoints.push_back(PointF{150, 150});
6403 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006404 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006405
chaviw9eaa22c2020-07-01 16:21:27 -07006406 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006407 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006408 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006409
chaviw9eaa22c2020-07-01 16:21:27 -07006410 // Update the transform so rotation is set for Window 2
6411 mWindow2->setWindowTransform(0, -1, 1, 0);
6412 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006413 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006414}
6415
chaviw9eaa22c2020-07-01 16:21:27 -07006416TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006417 mWindow2->setWindowScale(0.5f, 0.5f);
6418
6419 // Touch Window 1
6420 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6421 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006422 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006423
6424 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006425 touchedPoints.push_back(PointF{150, 150});
6426 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006427
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006428 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006429
6430 // Move both windows
6431 touchedPoints = {{20, 20}, {175, 175}};
6432 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6433 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6434
chaviw9eaa22c2020-07-01 16:21:27 -07006435 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006436
chaviw9eaa22c2020-07-01 16:21:27 -07006437 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006438 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006439 expectedPoints.pop_back();
6440
6441 // Touch Window 2
6442 mWindow2->setWindowTransform(0, -1, 1, 0);
6443 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006444 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006445
6446 // Move both windows
6447 touchedPoints = {{20, 20}, {175, 175}};
6448 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6449 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6450
6451 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006452}
6453
6454TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6455 mWindow1->setWindowScale(0.5f, 0.5f);
6456
6457 // Touch Window 1
6458 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6459 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006460 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006461
6462 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006463 touchedPoints.push_back(PointF{150, 150});
6464 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006465
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006466 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006467
6468 // Move both windows
6469 touchedPoints = {{20, 20}, {175, 175}};
6470 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6471 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6472
chaviw9eaa22c2020-07-01 16:21:27 -07006473 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006474}
6475
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006476/**
6477 * When one of the windows is slippery, the touch should not slip into the other window with the
6478 * same input channel.
6479 */
6480TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6481 mWindow1->setSlippery(true);
6482 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6483
6484 // Touch down in window 1
6485 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6486 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6487 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6488
6489 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6490 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6491 // getting generated.
6492 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6493 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6494
6495 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6496}
6497
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006498/**
6499 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6500 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6501 * that the pointer is hovering over may have a different transform.
6502 */
6503TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6504 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6505
6506 // Start hover in window 1
6507 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6508 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6509 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6510 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6511
6512 // Move hover to window 2.
6513 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6514 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6515
6516 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6517 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6518 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6519}
6520
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006521class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6522 virtual void SetUp() override {
6523 InputDispatcherTest::SetUp();
6524
Chris Yea209fde2020-07-22 13:54:51 -07006525 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006526 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006527 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6528 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006529 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006530 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006531 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006532
6533 // Set focused application.
6534 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6535
6536 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006537 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006538 mWindow->consumeFocusEvent(true);
6539 }
6540
6541 virtual void TearDown() override {
6542 InputDispatcherTest::TearDown();
6543 mWindow.clear();
6544 }
6545
6546protected:
Chris Yea209fde2020-07-22 13:54:51 -07006547 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006548 sp<FakeWindowHandle> mWindow;
6549 static constexpr PointF WINDOW_LOCATION = {20, 20};
6550
6551 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006553 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6554 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006556 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6557 WINDOW_LOCATION));
6558 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006559
6560 sp<FakeWindowHandle> addSpyWindow() {
6561 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006562 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006563 spy->setTrustedOverlay(true);
6564 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006565 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006566 spy->setDispatchingTimeout(30ms);
6567 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6568 return spy;
6569 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006570};
6571
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006572// Send a tap and respond, which should not cause an ANR.
6573TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6574 tapOnWindow();
6575 mWindow->consumeMotionDown();
6576 mWindow->consumeMotionUp();
6577 ASSERT_TRUE(mDispatcher->waitForIdle());
6578 mFakePolicy->assertNotifyAnrWasNotCalled();
6579}
6580
6581// Send a regular key and respond, which should not cause an ANR.
6582TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006584 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6585 ASSERT_TRUE(mDispatcher->waitForIdle());
6586 mFakePolicy->assertNotifyAnrWasNotCalled();
6587}
6588
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006589TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6590 mWindow->setFocusable(false);
6591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6592 mWindow->consumeFocusEvent(false);
6593
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006594 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006595 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6596 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6597 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006599 // Key will not go to window because we have no focused window.
6600 // The 'no focused window' ANR timer should start instead.
6601
6602 // Now, the focused application goes away.
6603 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6604 // The key should get dropped and there should be no ANR.
6605
6606 ASSERT_TRUE(mDispatcher->waitForIdle());
6607 mFakePolicy->assertNotifyAnrWasNotCalled();
6608}
6609
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006610// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006611// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6612// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006613TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006615 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6616 WINDOW_LOCATION));
6617
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006618 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6619 ASSERT_TRUE(sequenceNum);
6620 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006621 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006622
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006623 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006624 mWindow->consumeMotionEvent(
6625 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006626 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006627 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006628}
6629
6630// Send a key to the app and have the app not respond right away.
6631TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6632 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006634 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6635 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006636 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006637 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006638 ASSERT_TRUE(mDispatcher->waitForIdle());
6639}
6640
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006641// We have a focused application, but no focused window
6642TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006643 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6645 mWindow->consumeFocusEvent(false);
6646
6647 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006649 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6650 WINDOW_LOCATION));
6651 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6652 mDispatcher->waitForIdle();
6653 mFakePolicy->assertNotifyAnrWasNotCalled();
6654
6655 // Once a focused event arrives, we get an ANR for this application
6656 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6657 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006658 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006659 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6660 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006661 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006662 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006663 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006664 ASSERT_TRUE(mDispatcher->waitForIdle());
6665}
6666
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006667/**
6668 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6669 * there will not be an ANR.
6670 */
6671TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6672 mWindow->setFocusable(false);
6673 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6674 mWindow->consumeFocusEvent(false);
6675
6676 KeyEvent event;
6677 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6678 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6679
6680 // Define a valid key down event that is stale (too old).
6681 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6682 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006683 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006684
6685 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6686
6687 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006688 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006689 InputEventInjectionSync::WAIT_FOR_RESULT,
6690 INJECT_EVENT_TIMEOUT, policyFlags);
6691 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6692 << "Injection should fail because the event is stale";
6693
6694 ASSERT_TRUE(mDispatcher->waitForIdle());
6695 mFakePolicy->assertNotifyAnrWasNotCalled();
6696 mWindow->assertNoEvents();
6697}
6698
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006699// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006700// Make sure that we don't notify policy twice about the same ANR.
6701TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006702 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006703 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6704 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006705
6706 // Once a focused event arrives, we get an ANR for this application
6707 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6708 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006709 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006710 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6711 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006712 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006713 const std::chrono::duration appTimeout =
6714 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6715 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006716
Vishnu Naire4df8752022-09-08 09:17:55 -07006717 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006718 // ANR should not be raised again. It is up to policy to do that if it desires.
6719 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006720
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006721 // If we now get a focused window, the ANR should stop, but the policy handles that via
6722 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006723 ASSERT_TRUE(mDispatcher->waitForIdle());
6724}
6725
6726// We have a focused application, but no focused window
6727TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006728 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006729 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6730 mWindow->consumeFocusEvent(false);
6731
6732 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006733 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006734 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006735 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6736 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006737
Vishnu Naire4df8752022-09-08 09:17:55 -07006738 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6739 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006740
6741 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006742 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006743 ASSERT_TRUE(mDispatcher->waitForIdle());
6744 mWindow->assertNoEvents();
6745}
6746
6747/**
6748 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6749 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6750 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6751 * the ANR mechanism should still work.
6752 *
6753 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6754 * DOWN event, while not responding on the second one.
6755 */
6756TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6757 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6758 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6759 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6760 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6761 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006762 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006763
6764 // Now send ACTION_UP, with identical timestamp
6765 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6766 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6767 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6768 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006769 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006770
6771 // We have now sent down and up. Let's consume first event and then ANR on the second.
6772 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6773 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006774 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006775}
6776
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006777// A spy window can receive an ANR
6778TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6779 sp<FakeWindowHandle> spy = addSpyWindow();
6780
6781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6782 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6783 WINDOW_LOCATION));
6784 mWindow->consumeMotionDown();
6785
6786 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6787 ASSERT_TRUE(sequenceNum);
6788 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006789 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006790
6791 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006792 spy->consumeMotionEvent(
6793 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006794 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006795 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006796}
6797
6798// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006800TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6801 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006802
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6804 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006805 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006807
6808 // Stuck on the ACTION_UP
6809 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006810 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006811
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006812 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006814 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6815 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006816
6817 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6818 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006819 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006820 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006821 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006822}
6823
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006824// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006825// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006826TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6827 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006828
6829 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006830 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6831 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006832
6833 mWindow->consumeMotionDown();
6834 // Stuck on the ACTION_UP
6835 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006836 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006837
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006838 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006839 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006840 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6841 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006842
6843 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6844 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006845 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006846 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006847 spy->assertNoEvents();
6848}
6849
6850TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6851 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6852
6853 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6854
6855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6856 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6857 WINDOW_LOCATION));
6858
6859 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6860 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6861 ASSERT_TRUE(consumeSeq);
6862
Prabir Pradhanedd96402022-02-15 01:46:16 -08006863 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006864
6865 monitor.finishEvent(*consumeSeq);
6866 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6867
6868 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006869 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006870}
6871
6872// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6873// process events, you don't get an anr. When the window later becomes unresponsive again, you
6874// get an ANR again.
6875// 1. tap -> block on ACTION_UP -> receive ANR
6876// 2. consume all pending events (= queue becomes healthy again)
6877// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6878TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6879 tapOnWindow();
6880
6881 mWindow->consumeMotionDown();
6882 // Block on ACTION_UP
6883 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006884 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006885 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6886 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006887 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888 mWindow->assertNoEvents();
6889
6890 tapOnWindow();
6891 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006892 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006893 mWindow->consumeMotionUp();
6894
6895 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006896 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006897 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006898 mWindow->assertNoEvents();
6899}
6900
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006901// If a connection remains unresponsive for a while, make sure policy is only notified once about
6902// it.
6903TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6906 WINDOW_LOCATION));
6907
6908 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006909 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006910 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006911 // 'notifyConnectionUnresponsive' should only be called once per connection
6912 mFakePolicy->assertNotifyAnrWasNotCalled();
6913 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006915 mWindow->consumeMotionEvent(
6916 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006917 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006918 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006919 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006920 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921}
6922
6923/**
6924 * If a window is processing a motion event, and then a key event comes in, the key event should
6925 * not to to the focused window until the motion is processed.
6926 *
6927 * Warning!!!
6928 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
6929 * and the injection timeout that we specify when injecting the key.
6930 * We must have the injection timeout (10ms) be smaller than
6931 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
6932 *
6933 * If that value changes, this test should also change.
6934 */
6935TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
6936 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6937 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6938
6939 tapOnWindow();
6940 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6941 ASSERT_TRUE(downSequenceNum);
6942 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6943 ASSERT_TRUE(upSequenceNum);
6944 // Don't finish the events yet, and send a key
6945 // Injection will "succeed" because we will eventually give up and send the key to the focused
6946 // window even if motions are still being processed. But because the injection timeout is short,
6947 // we will receive INJECTION_TIMED_OUT as the result.
6948
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006949 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006950 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006951 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6952 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006953 // Key will not be sent to the window, yet, because the window is still processing events
6954 // and the key remains pending, waiting for the touch events to be processed
6955 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6956 ASSERT_FALSE(keySequenceNum);
6957
6958 std::this_thread::sleep_for(500ms);
6959 // if we wait long enough though, dispatcher will give up, and still send the key
6960 // to the focused window, even though we have not yet finished the motion event
6961 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6962 mWindow->finishEvent(*downSequenceNum);
6963 mWindow->finishEvent(*upSequenceNum);
6964}
6965
6966/**
6967 * If a window is processing a motion event, and then a key event comes in, the key event should
6968 * not go to the focused window until the motion is processed.
6969 * If then a new motion comes in, then the pending key event should be going to the currently
6970 * focused window right away.
6971 */
6972TEST_F(InputDispatcherSingleWindowAnr,
6973 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
6974 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
6975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6976
6977 tapOnWindow();
6978 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
6979 ASSERT_TRUE(downSequenceNum);
6980 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
6981 ASSERT_TRUE(upSequenceNum);
6982 // Don't finish the events yet, and send a key
6983 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006984 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006985 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6986 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006987 // At this point, key is still pending, and should not be sent to the application yet.
6988 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
6989 ASSERT_FALSE(keySequenceNum);
6990
6991 // Now tap down again. It should cause the pending key to go to the focused window right away.
6992 tapOnWindow();
6993 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
6994 // the other events yet. We can finish events in any order.
6995 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
6996 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
6997 mWindow->consumeMotionDown();
6998 mWindow->consumeMotionUp();
6999 mWindow->assertNoEvents();
7000}
7001
7002class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7003 virtual void SetUp() override {
7004 InputDispatcherTest::SetUp();
7005
Chris Yea209fde2020-07-22 13:54:51 -07007006 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007007 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007008 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7009 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007010 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007011 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007012 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007013
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007014 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7015 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007016 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007017 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007018
7019 // Set focused application.
7020 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007021 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007022
7023 // Expect one focus window exist in display.
7024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007025 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007026 mFocusedWindow->consumeFocusEvent(true);
7027 }
7028
7029 virtual void TearDown() override {
7030 InputDispatcherTest::TearDown();
7031
7032 mUnfocusedWindow.clear();
7033 mFocusedWindow.clear();
7034 }
7035
7036protected:
Chris Yea209fde2020-07-22 13:54:51 -07007037 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007038 sp<FakeWindowHandle> mUnfocusedWindow;
7039 sp<FakeWindowHandle> mFocusedWindow;
7040 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7041 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7042 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7043
7044 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7045
7046 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7047
7048private:
7049 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007051 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7052 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007054 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7055 location));
7056 }
7057};
7058
7059// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7060// should be ANR'd first.
7061TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007063 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7064 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007067 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007068 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007069 // We consumed all events, so no ANR
7070 ASSERT_TRUE(mDispatcher->waitForIdle());
7071 mFakePolicy->assertNotifyAnrWasNotCalled();
7072
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007074 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7075 FOCUSED_WINDOW_LOCATION));
7076 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7077 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007078
7079 const std::chrono::duration timeout =
7080 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007081 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007082 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7083 // sequence to make it consistent
7084 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007085 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007086 mFocusedWindow->consumeMotionDown();
7087 // This cancel is generated because the connection was unresponsive
7088 mFocusedWindow->consumeMotionCancel();
7089 mFocusedWindow->assertNoEvents();
7090 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007091 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007092 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7093 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007094 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007095}
7096
7097// If we have 2 windows with identical timeouts that are both unresponsive,
7098// it doesn't matter which order they should have ANR.
7099// But we should receive ANR for both.
7100TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7101 // Set the timeout for unfocused window to match the focused window
7102 mUnfocusedWindow->setDispatchingTimeout(10ms);
7103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7104
7105 tapOnFocusedWindow();
7106 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007107 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7108 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7109 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007110
7111 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007112 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7113 mFocusedWindow->getToken() == anrConnectionToken2);
7114 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7115 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007116
7117 ASSERT_TRUE(mDispatcher->waitForIdle());
7118 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007119
7120 mFocusedWindow->consumeMotionDown();
7121 mFocusedWindow->consumeMotionUp();
7122 mUnfocusedWindow->consumeMotionOutside();
7123
Prabir Pradhanedd96402022-02-15 01:46:16 -08007124 sp<IBinder> responsiveToken1, responsiveToken2;
7125 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7126 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007127
7128 // Both applications should be marked as responsive, in any order
7129 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7130 mFocusedWindow->getToken() == responsiveToken2);
7131 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7132 mUnfocusedWindow->getToken() == responsiveToken2);
7133 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007134}
7135
7136// If a window is already not responding, the second tap on the same window should be ignored.
7137// We should also log an error to account for the dropped event (not tested here).
7138// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7139TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7140 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007141 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007142 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007143 // Receive the events, but don't respond
7144 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7145 ASSERT_TRUE(downEventSequenceNum);
7146 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7147 ASSERT_TRUE(upEventSequenceNum);
7148 const std::chrono::duration timeout =
7149 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007150 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007151
7152 // Tap once again
7153 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007154 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007155 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7156 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007157 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007158 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7159 FOCUSED_WINDOW_LOCATION));
7160 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7161 // valid touch target
7162 mUnfocusedWindow->assertNoEvents();
7163
7164 // Consume the first tap
7165 mFocusedWindow->finishEvent(*downEventSequenceNum);
7166 mFocusedWindow->finishEvent(*upEventSequenceNum);
7167 ASSERT_TRUE(mDispatcher->waitForIdle());
7168 // The second tap did not go to the focused window
7169 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007170 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007171 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7172 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007173 mFakePolicy->assertNotifyAnrWasNotCalled();
7174}
7175
7176// If you tap outside of all windows, there will not be ANR
7177TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007178 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007179 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7180 LOCATION_OUTSIDE_ALL_WINDOWS));
7181 ASSERT_TRUE(mDispatcher->waitForIdle());
7182 mFakePolicy->assertNotifyAnrWasNotCalled();
7183}
7184
7185// Since the focused window is paused, tapping on it should not produce any events
7186TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7187 mFocusedWindow->setPaused(true);
7188 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7189
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007190 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007191 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7192 FOCUSED_WINDOW_LOCATION));
7193
7194 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7195 ASSERT_TRUE(mDispatcher->waitForIdle());
7196 // Should not ANR because the window is paused, and touches shouldn't go to it
7197 mFakePolicy->assertNotifyAnrWasNotCalled();
7198
7199 mFocusedWindow->assertNoEvents();
7200 mUnfocusedWindow->assertNoEvents();
7201}
7202
7203/**
7204 * If a window is processing a motion event, and then a key event comes in, the key event should
7205 * not to to the focused window until the motion is processed.
7206 * If a different window becomes focused at this time, the key should go to that window instead.
7207 *
7208 * Warning!!!
7209 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7210 * and the injection timeout that we specify when injecting the key.
7211 * We must have the injection timeout (10ms) be smaller than
7212 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7213 *
7214 * If that value changes, this test should also change.
7215 */
7216TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7217 // Set a long ANR timeout to prevent it from triggering
7218 mFocusedWindow->setDispatchingTimeout(2s);
7219 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7220
7221 tapOnUnfocusedWindow();
7222 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7223 ASSERT_TRUE(downSequenceNum);
7224 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7225 ASSERT_TRUE(upSequenceNum);
7226 // Don't finish the events yet, and send a key
7227 // Injection will succeed because we will eventually give up and send the key to the focused
7228 // window even if motions are still being processed.
7229
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007230 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007231 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7232 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007234 // Key will not be sent to the window, yet, because the window is still processing events
7235 // and the key remains pending, waiting for the touch events to be processed
7236 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7237 ASSERT_FALSE(keySequenceNum);
7238
7239 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007240 mFocusedWindow->setFocusable(false);
7241 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007242 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007243 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007244
7245 // Focus events should precede the key events
7246 mUnfocusedWindow->consumeFocusEvent(true);
7247 mFocusedWindow->consumeFocusEvent(false);
7248
7249 // Finish the tap events, which should unblock dispatcher
7250 mUnfocusedWindow->finishEvent(*downSequenceNum);
7251 mUnfocusedWindow->finishEvent(*upSequenceNum);
7252
7253 // Now that all queues are cleared and no backlog in the connections, the key event
7254 // can finally go to the newly focused "mUnfocusedWindow".
7255 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7256 mFocusedWindow->assertNoEvents();
7257 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007258 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007259}
7260
7261// When the touch stream is split across 2 windows, and one of them does not respond,
7262// then ANR should be raised and the touch should be canceled for the unresponsive window.
7263// The other window should not be affected by that.
7264TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7265 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007266 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7267 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7268 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007269 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007270 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271
7272 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007273 mDispatcher->notifyMotion(
7274 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7275 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007276
7277 const std::chrono::duration timeout =
7278 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007279 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007280
7281 mUnfocusedWindow->consumeMotionDown();
7282 mFocusedWindow->consumeMotionDown();
7283 // Focused window may or may not receive ACTION_MOVE
7284 // But it should definitely receive ACTION_CANCEL due to the ANR
7285 InputEvent* event;
7286 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7287 ASSERT_TRUE(moveOrCancelSequenceNum);
7288 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7289 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007290 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007291 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7292 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7293 mFocusedWindow->consumeMotionCancel();
7294 } else {
7295 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7296 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007297 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007298 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7299 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007300
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007301 mUnfocusedWindow->assertNoEvents();
7302 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007303 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007304}
7305
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007306/**
7307 * If we have no focused window, and a key comes in, we start the ANR timer.
7308 * The focused application should add a focused window before the timer runs out to prevent ANR.
7309 *
7310 * If the user touches another application during this time, the key should be dropped.
7311 * Next, if a new focused window comes in, without toggling the focused application,
7312 * then no ANR should occur.
7313 *
7314 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7315 * but in some cases the policy may not update the focused application.
7316 */
7317TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7318 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7319 std::make_shared<FakeApplicationHandle>();
7320 focusedApplication->setDispatchingTimeout(60ms);
7321 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7322 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7323 mFocusedWindow->setFocusable(false);
7324
7325 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7326 mFocusedWindow->consumeFocusEvent(false);
7327
7328 // Send a key. The ANR timer should start because there is no focused window.
7329 // 'focusedApplication' will get blamed if this timer completes.
7330 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007331 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007332 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7333 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7334 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007336
7337 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7338 // then the injected touches won't cause the focused event to get dropped.
7339 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7340 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7341 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7342 // For this test, it means that the key would get delivered to the window once it becomes
7343 // focused.
7344 std::this_thread::sleep_for(10ms);
7345
7346 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007347 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7348 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7349 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007350
7351 // We do not consume the motion right away, because that would require dispatcher to first
7352 // process (== drop) the key event, and by that time, ANR will be raised.
7353 // Set the focused window first.
7354 mFocusedWindow->setFocusable(true);
7355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7356 setFocusedWindow(mFocusedWindow);
7357 mFocusedWindow->consumeFocusEvent(true);
7358 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7359 // to another application. This could be a bug / behaviour in the policy.
7360
7361 mUnfocusedWindow->consumeMotionDown();
7362
7363 ASSERT_TRUE(mDispatcher->waitForIdle());
7364 // Should not ANR because we actually have a focused window. It was just added too slowly.
7365 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7366}
7367
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007368// These tests ensure we cannot send touch events to a window that's positioned behind a window
7369// that has feature NO_INPUT_CHANNEL.
7370// Layout:
7371// Top (closest to user)
7372// mNoInputWindow (above all windows)
7373// mBottomWindow
7374// Bottom (furthest from user)
7375class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7376 virtual void SetUp() override {
7377 InputDispatcherTest::SetUp();
7378
7379 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007380 mNoInputWindow =
7381 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7382 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007383 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007384 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007385 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7386 // It's perfectly valid for this window to not have an associated input channel
7387
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007388 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7389 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007390 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7391
7392 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7393 }
7394
7395protected:
7396 std::shared_ptr<FakeApplicationHandle> mApplication;
7397 sp<FakeWindowHandle> mNoInputWindow;
7398 sp<FakeWindowHandle> mBottomWindow;
7399};
7400
7401TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7402 PointF touchedPoint = {10, 10};
7403
Prabir Pradhan678438e2023-04-13 19:32:51 +00007404 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7405 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7406 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007407
7408 mNoInputWindow->assertNoEvents();
7409 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7410 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7411 // and therefore should prevent mBottomWindow from receiving touches
7412 mBottomWindow->assertNoEvents();
7413}
7414
7415/**
7416 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7417 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7418 */
7419TEST_F(InputDispatcherMultiWindowOcclusionTests,
7420 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007421 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7422 "Window with input channel and NO_INPUT_CHANNEL",
7423 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007424
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007425 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007426 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7427 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7428
7429 PointF touchedPoint = {10, 10};
7430
Prabir Pradhan678438e2023-04-13 19:32:51 +00007431 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7432 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7433 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007434
7435 mNoInputWindow->assertNoEvents();
7436 mBottomWindow->assertNoEvents();
7437}
7438
Vishnu Nair958da932020-08-21 17:12:37 -07007439class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7440protected:
7441 std::shared_ptr<FakeApplicationHandle> mApp;
7442 sp<FakeWindowHandle> mWindow;
7443 sp<FakeWindowHandle> mMirror;
7444
7445 virtual void SetUp() override {
7446 InputDispatcherTest::SetUp();
7447 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007448 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7449 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7450 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007451 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7452 mWindow->setFocusable(true);
7453 mMirror->setFocusable(true);
7454 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7455 }
7456};
7457
7458TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7459 // Request focus on a mirrored window
7460 setFocusedWindow(mMirror);
7461
7462 // window gets focused
7463 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7465 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007466 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7467}
7468
7469// A focused & mirrored window remains focused only if the window and its mirror are both
7470// focusable.
7471TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7472 setFocusedWindow(mMirror);
7473
7474 // window gets focused
7475 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007478 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7480 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007481 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7482
7483 mMirror->setFocusable(false);
7484 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7485
7486 // window loses focus since one of the windows associated with the token in not focusable
7487 mWindow->consumeFocusEvent(false);
7488
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007489 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7490 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007491 mWindow->assertNoEvents();
7492}
7493
7494// A focused & mirrored window remains focused until the window and its mirror both become
7495// invisible.
7496TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7497 setFocusedWindow(mMirror);
7498
7499 // window gets focused
7500 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7502 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007503 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7505 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007506 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7507
7508 mMirror->setVisible(false);
7509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7510
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7512 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007513 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7515 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007516 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7517
7518 mWindow->setVisible(false);
7519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7520
7521 // window loses focus only after all windows associated with the token become invisible.
7522 mWindow->consumeFocusEvent(false);
7523
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007524 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7525 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007526 mWindow->assertNoEvents();
7527}
7528
7529// A focused & mirrored window remains focused until both windows are removed.
7530TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7531 setFocusedWindow(mMirror);
7532
7533 // window gets focused
7534 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7536 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007537 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7539 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007540 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7541
7542 // single window is removed but the window token remains focused
7543 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7544
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7546 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007547 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7549 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007550 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7551
7552 // Both windows are removed
7553 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7554 mWindow->consumeFocusEvent(false);
7555
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007556 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7557 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007558 mWindow->assertNoEvents();
7559}
7560
7561// Focus request can be pending until one window becomes visible.
7562TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7563 // Request focus on an invisible mirror.
7564 mWindow->setVisible(false);
7565 mMirror->setVisible(false);
7566 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7567 setFocusedWindow(mMirror);
7568
7569 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007571 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7572 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007573
7574 mMirror->setVisible(true);
7575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7576
7577 // window gets focused
7578 mWindow->consumeFocusEvent(true);
7579 // window gets the pending key event
7580 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7581}
Prabir Pradhan99987712020-11-10 18:43:05 -08007582
7583class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7584protected:
7585 std::shared_ptr<FakeApplicationHandle> mApp;
7586 sp<FakeWindowHandle> mWindow;
7587 sp<FakeWindowHandle> mSecondWindow;
7588
7589 void SetUp() override {
7590 InputDispatcherTest::SetUp();
7591 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007592 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007593 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007594 mSecondWindow =
7595 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007596 mSecondWindow->setFocusable(true);
7597
7598 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7600
7601 setFocusedWindow(mWindow);
7602 mWindow->consumeFocusEvent(true);
7603 }
7604
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007605 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007606 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007607 }
7608
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007609 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7610 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007611 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007612 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7613 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007614 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007615 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007616 }
7617};
7618
7619TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7620 // Ensure that capture cannot be obtained for unfocused windows.
7621 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7622 mFakePolicy->assertSetPointerCaptureNotCalled();
7623 mSecondWindow->assertNoEvents();
7624
7625 // Ensure that capture can be enabled from the focus window.
7626 requestAndVerifyPointerCapture(mWindow, true);
7627
7628 // Ensure that capture cannot be disabled from a window that does not have capture.
7629 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7630 mFakePolicy->assertSetPointerCaptureNotCalled();
7631
7632 // Ensure that capture can be disabled from the window with capture.
7633 requestAndVerifyPointerCapture(mWindow, false);
7634}
7635
7636TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007637 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007638
7639 setFocusedWindow(mSecondWindow);
7640
7641 // Ensure that the capture disabled event was sent first.
7642 mWindow->consumeCaptureEvent(false);
7643 mWindow->consumeFocusEvent(false);
7644 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007645 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007646
7647 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007648 notifyPointerCaptureChanged({});
7649 notifyPointerCaptureChanged(request);
7650 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007651 mWindow->assertNoEvents();
7652 mSecondWindow->assertNoEvents();
7653 mFakePolicy->assertSetPointerCaptureNotCalled();
7654}
7655
7656TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007657 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007658
7659 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007660 notifyPointerCaptureChanged({});
7661 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007662
7663 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007664 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007665 mWindow->consumeCaptureEvent(false);
7666 mWindow->assertNoEvents();
7667}
7668
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007669TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7670 requestAndVerifyPointerCapture(mWindow, true);
7671
7672 // The first window loses focus.
7673 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007674 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007675 mWindow->consumeCaptureEvent(false);
7676
7677 // Request Pointer Capture from the second window before the notification from InputReader
7678 // arrives.
7679 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007680 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007681
7682 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007683 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007684
7685 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007686 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007687
7688 mSecondWindow->consumeFocusEvent(true);
7689 mSecondWindow->consumeCaptureEvent(true);
7690}
7691
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007692TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7693 // App repeatedly enables and disables capture.
7694 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7695 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7696 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7697 mFakePolicy->assertSetPointerCaptureCalled(false);
7698 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7699 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7700
7701 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7702 // first request is now stale, this should do nothing.
7703 notifyPointerCaptureChanged(firstRequest);
7704 mWindow->assertNoEvents();
7705
7706 // InputReader notifies that the second request was enabled.
7707 notifyPointerCaptureChanged(secondRequest);
7708 mWindow->consumeCaptureEvent(true);
7709}
7710
Prabir Pradhan7092e262022-05-03 16:51:09 +00007711TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7712 requestAndVerifyPointerCapture(mWindow, true);
7713
7714 // App toggles pointer capture off and on.
7715 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7716 mFakePolicy->assertSetPointerCaptureCalled(false);
7717
7718 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7719 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7720
7721 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7722 // preceding "disable" request.
7723 notifyPointerCaptureChanged(enableRequest);
7724
7725 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7726 // any notifications.
7727 mWindow->assertNoEvents();
7728}
7729
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007730class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7731protected:
7732 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007733
7734 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7735 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7736
7737 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7738 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7739
7740 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7741 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7742 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7743 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7744 MAXIMUM_OBSCURING_OPACITY);
7745
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007746 static const int32_t TOUCHED_APP_UID = 10001;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007747 static const int32_t APP_B_UID = 10002;
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007748 static const int32_t APP_C_UID = 10003;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007749
7750 sp<FakeWindowHandle> mTouchWindow;
7751
7752 virtual void SetUp() override {
7753 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007754 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007755 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7756 }
7757
7758 virtual void TearDown() override {
7759 InputDispatcherTest::TearDown();
7760 mTouchWindow.clear();
7761 }
7762
chaviw3277faf2021-05-19 16:45:23 -05007763 sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, TouchOcclusionMode mode,
7764 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007765 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007766 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007767 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007768 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007769 return window;
7770 }
7771
7772 sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
7773 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7774 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007775 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007776 // Generate an arbitrary PID based on the UID
7777 window->setOwnerInfo(1777 + (uid % 10000), uid);
7778 return window;
7779 }
7780
7781 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007782 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7783 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7784 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007785 }
7786};
7787
7788TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007789 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007790 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007791 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007792
7793 touch();
7794
7795 mTouchWindow->assertNoEvents();
7796}
7797
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007798TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007799 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7800 const sp<FakeWindowHandle>& w =
7801 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7802 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7803
7804 touch();
7805
7806 mTouchWindow->assertNoEvents();
7807}
7808
7809TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007810 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7811 const sp<FakeWindowHandle>& w =
7812 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7814
7815 touch();
7816
7817 w->assertNoEvents();
7818}
7819
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007820TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007821 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7822 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007823
7824 touch();
7825
7826 mTouchWindow->consumeAnyMotionDown();
7827}
7828
7829TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007830 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007831 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007832 w->setFrame(Rect(0, 0, 50, 50));
7833 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007834
7835 touch({PointF{100, 100}});
7836
7837 mTouchWindow->consumeAnyMotionDown();
7838}
7839
7840TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007841 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007842 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007843 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7844
7845 touch();
7846
7847 mTouchWindow->consumeAnyMotionDown();
7848}
7849
7850TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7851 const sp<FakeWindowHandle>& w =
7852 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007854
7855 touch();
7856
7857 mTouchWindow->consumeAnyMotionDown();
7858}
7859
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007860TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7861 const sp<FakeWindowHandle>& w =
7862 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7864
7865 touch();
7866
7867 w->assertNoEvents();
7868}
7869
7870/**
7871 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
7872 * inside) while letting them pass-through. Note that even though touch passes through the occluding
7873 * window, the occluding window will still receive ACTION_OUTSIDE event.
7874 */
7875TEST_F(InputDispatcherUntrustedTouchesTest,
7876 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
7877 const sp<FakeWindowHandle>& w =
7878 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007879 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007880 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7881
7882 touch();
7883
7884 w->consumeMotionOutside();
7885}
7886
7887TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
7888 const sp<FakeWindowHandle>& w =
7889 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007890 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007891 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7892
7893 touch();
7894
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08007895 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007896}
7897
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007898TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007899 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007900 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7901 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007902 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7903
7904 touch();
7905
7906 mTouchWindow->consumeAnyMotionDown();
7907}
7908
7909TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
7910 const sp<FakeWindowHandle>& w =
7911 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7912 MAXIMUM_OBSCURING_OPACITY);
7913 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007914
7915 touch();
7916
7917 mTouchWindow->consumeAnyMotionDown();
7918}
7919
7920TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007921 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007922 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7923 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007924 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7925
7926 touch();
7927
7928 mTouchWindow->assertNoEvents();
7929}
7930
7931TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
7932 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
7933 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007934 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7935 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007936 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007937 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7938 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007939 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7940
7941 touch();
7942
7943 mTouchWindow->assertNoEvents();
7944}
7945
7946TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
7947 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
7948 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007949 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
7950 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007951 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007952 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
7953 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
7955
7956 touch();
7957
7958 mTouchWindow->consumeAnyMotionDown();
7959}
7960
7961TEST_F(InputDispatcherUntrustedTouchesTest,
7962 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
7963 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007964 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7965 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007966 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007967 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7968 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007969 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
7970
7971 touch();
7972
7973 mTouchWindow->consumeAnyMotionDown();
7974}
7975
7976TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
7977 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007978 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7979 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007980 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007981 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
7982 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007983 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007984
7985 touch();
7986
7987 mTouchWindow->assertNoEvents();
7988}
7989
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007990TEST_F(InputDispatcherUntrustedTouchesTest,
7991 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
7992 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007993 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
7994 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007995 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00007996 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
7997 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007998 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
7999
8000 touch();
8001
8002 mTouchWindow->assertNoEvents();
8003}
8004
8005TEST_F(InputDispatcherUntrustedTouchesTest,
8006 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8007 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008008 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8009 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008010 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008011 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8012 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008013 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8014
8015 touch();
8016
8017 mTouchWindow->consumeAnyMotionDown();
8018}
8019
8020TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8021 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008022 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8023 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008024 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8025
8026 touch();
8027
8028 mTouchWindow->consumeAnyMotionDown();
8029}
8030
8031TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8032 const sp<FakeWindowHandle>& w =
8033 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8034 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8035
8036 touch();
8037
8038 mTouchWindow->consumeAnyMotionDown();
8039}
8040
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008041TEST_F(InputDispatcherUntrustedTouchesTest,
8042 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8043 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8044 const sp<FakeWindowHandle>& w =
8045 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8047
8048 touch();
8049
8050 mTouchWindow->assertNoEvents();
8051}
8052
8053TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8054 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8055 const sp<FakeWindowHandle>& w =
8056 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8057 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8058
8059 touch();
8060
8061 mTouchWindow->consumeAnyMotionDown();
8062}
8063
8064TEST_F(InputDispatcherUntrustedTouchesTest,
8065 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8066 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8067 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008068 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8069 OPACITY_ABOVE_THRESHOLD);
8070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8071
8072 touch();
8073
8074 mTouchWindow->consumeAnyMotionDown();
8075}
8076
8077TEST_F(InputDispatcherUntrustedTouchesTest,
8078 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8079 const sp<FakeWindowHandle>& w1 =
8080 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8081 OPACITY_BELOW_THRESHOLD);
8082 const sp<FakeWindowHandle>& w2 =
8083 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8084 OPACITY_BELOW_THRESHOLD);
8085 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8086
8087 touch();
8088
8089 mTouchWindow->assertNoEvents();
8090}
8091
8092/**
8093 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8094 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8095 * (which alone would result in allowing touches) does not affect the blocking behavior.
8096 */
8097TEST_F(InputDispatcherUntrustedTouchesTest,
8098 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8099 const sp<FakeWindowHandle>& wB =
8100 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8101 OPACITY_BELOW_THRESHOLD);
8102 const sp<FakeWindowHandle>& wC =
8103 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8104 OPACITY_BELOW_THRESHOLD);
8105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8106
8107 touch();
8108
8109 mTouchWindow->assertNoEvents();
8110}
8111
8112/**
8113 * This test is testing that a window from a different UID but with same application token doesn't
8114 * block the touch. Apps can share the application token for close UI collaboration for example.
8115 */
8116TEST_F(InputDispatcherUntrustedTouchesTest,
8117 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8118 const sp<FakeWindowHandle>& w =
8119 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8120 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8122
8123 touch();
8124
8125 mTouchWindow->consumeAnyMotionDown();
8126}
8127
arthurhungb89ccb02020-12-30 16:19:01 +08008128class InputDispatcherDragTests : public InputDispatcherTest {
8129protected:
8130 std::shared_ptr<FakeApplicationHandle> mApp;
8131 sp<FakeWindowHandle> mWindow;
8132 sp<FakeWindowHandle> mSecondWindow;
8133 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008134 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008135 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8136 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008137
8138 void SetUp() override {
8139 InputDispatcherTest::SetUp();
8140 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008141 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008142 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008143
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008144 mSecondWindow =
8145 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008146 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008147
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008148 mSpyWindow =
8149 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008150 mSpyWindow->setSpy(true);
8151 mSpyWindow->setTrustedOverlay(true);
8152 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8153
arthurhungb89ccb02020-12-30 16:19:01 +08008154 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008155 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008156 }
8157
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008158 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8159 switch (fromSource) {
8160 case AINPUT_SOURCE_TOUCHSCREEN:
8161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8162 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8163 ADISPLAY_ID_DEFAULT, {50, 50}))
8164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8165 break;
8166 case AINPUT_SOURCE_STYLUS:
8167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8168 injectMotionEvent(
8169 mDispatcher,
8170 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8171 AINPUT_SOURCE_STYLUS)
8172 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008173 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008174 .x(50)
8175 .y(50))
8176 .build()));
8177 break;
8178 case AINPUT_SOURCE_MOUSE:
8179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8180 injectMotionEvent(
8181 mDispatcher,
8182 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8183 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8184 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008185 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008186 .x(50)
8187 .y(50))
8188 .build()));
8189 break;
8190 default:
8191 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8192 }
arthurhungb89ccb02020-12-30 16:19:01 +08008193
8194 // Window should receive motion event.
8195 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008196 // Spy window should also receive motion event
8197 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008198 }
8199
8200 // Start performing drag, we will create a drag window and transfer touch to it.
8201 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8202 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008203 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008204 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008205 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008206 }
arthurhungb89ccb02020-12-30 16:19:01 +08008207
8208 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008209 mDragWindow =
8210 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008211 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008212 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008213 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008214
8215 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008216 bool transferred =
8217 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008218 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008219 if (transferred) {
8220 mWindow->consumeMotionCancel();
8221 mDragWindow->consumeMotionDown();
8222 }
8223 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008224 }
8225};
8226
8227TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008228 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008229
8230 // Move on window.
8231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8232 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8233 ADISPLAY_ID_DEFAULT, {50, 50}))
8234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8235 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8236 mWindow->consumeDragEvent(false, 50, 50);
8237 mSecondWindow->assertNoEvents();
8238
8239 // Move to another window.
8240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8241 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8242 ADISPLAY_ID_DEFAULT, {150, 50}))
8243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8244 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8245 mWindow->consumeDragEvent(true, 150, 50);
8246 mSecondWindow->consumeDragEvent(false, 50, 50);
8247
8248 // Move back to original window.
8249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8250 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8251 ADISPLAY_ID_DEFAULT, {50, 50}))
8252 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8253 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8254 mWindow->consumeDragEvent(false, 50, 50);
8255 mSecondWindow->consumeDragEvent(true, -50, 50);
8256
8257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8258 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8260 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8261 mWindow->assertNoEvents();
8262 mSecondWindow->assertNoEvents();
8263}
8264
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008265TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008266 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008267
8268 // No cancel event after drag start
8269 mSpyWindow->assertNoEvents();
8270
8271 const MotionEvent secondFingerDownEvent =
8272 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8273 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008274 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8275 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008276 .build();
8277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8278 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8279 InputEventInjectionSync::WAIT_FOR_RESULT))
8280 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8281
8282 // Receives cancel for first pointer after next pointer down
8283 mSpyWindow->consumeMotionCancel();
8284 mSpyWindow->consumeMotionDown();
8285
8286 mSpyWindow->assertNoEvents();
8287}
8288
arthurhungf452d0b2021-01-06 00:19:52 +08008289TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008290 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008291
8292 // Move on window.
8293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8294 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8295 ADISPLAY_ID_DEFAULT, {50, 50}))
8296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8297 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8298 mWindow->consumeDragEvent(false, 50, 50);
8299 mSecondWindow->assertNoEvents();
8300
8301 // Move to another window.
8302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8303 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8304 ADISPLAY_ID_DEFAULT, {150, 50}))
8305 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8306 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8307 mWindow->consumeDragEvent(true, 150, 50);
8308 mSecondWindow->consumeDragEvent(false, 50, 50);
8309
8310 // drop to another window.
8311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8312 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8313 {150, 50}))
8314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8315 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8316 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8317 mWindow->assertNoEvents();
8318 mSecondWindow->assertNoEvents();
8319}
8320
arthurhung6d4bed92021-03-17 11:59:33 +08008321TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008322 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008323
8324 // Move on window and keep button pressed.
8325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8326 injectMotionEvent(mDispatcher,
8327 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8328 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008329 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008330 .build()))
8331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8332 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8333 mWindow->consumeDragEvent(false, 50, 50);
8334 mSecondWindow->assertNoEvents();
8335
8336 // Move to another window and release button, expect to drop item.
8337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8338 injectMotionEvent(mDispatcher,
8339 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8340 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008341 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008342 .build()))
8343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8344 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8345 mWindow->assertNoEvents();
8346 mSecondWindow->assertNoEvents();
8347 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8348
8349 // nothing to the window.
8350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8351 injectMotionEvent(mDispatcher,
8352 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8353 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008354 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008355 .build()))
8356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8357 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8358 mWindow->assertNoEvents();
8359 mSecondWindow->assertNoEvents();
8360}
8361
Arthur Hung54745652022-04-20 07:17:41 +00008362TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008363 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008364
8365 // Set second window invisible.
8366 mSecondWindow->setVisible(false);
8367 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8368
8369 // Move on window.
8370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8371 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8372 ADISPLAY_ID_DEFAULT, {50, 50}))
8373 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8374 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8375 mWindow->consumeDragEvent(false, 50, 50);
8376 mSecondWindow->assertNoEvents();
8377
8378 // Move to another window.
8379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8380 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8381 ADISPLAY_ID_DEFAULT, {150, 50}))
8382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8383 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8384 mWindow->consumeDragEvent(true, 150, 50);
8385 mSecondWindow->assertNoEvents();
8386
8387 // drop to another window.
8388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8389 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8390 {150, 50}))
8391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8392 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8393 mFakePolicy->assertDropTargetEquals(nullptr);
8394 mWindow->assertNoEvents();
8395 mSecondWindow->assertNoEvents();
8396}
8397
Arthur Hung54745652022-04-20 07:17:41 +00008398TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008399 // Ensure window could track pointerIds if it didn't support split touch.
8400 mWindow->setPreventSplitting(true);
8401
Arthur Hung54745652022-04-20 07:17:41 +00008402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8403 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8404 {50, 50}))
8405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8406 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8407
8408 const MotionEvent secondFingerDownEvent =
8409 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8410 .displayId(ADISPLAY_ID_DEFAULT)
8411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008414 .build();
8415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8416 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8417 InputEventInjectionSync::WAIT_FOR_RESULT))
8418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008419 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008420
8421 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008422 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008423}
8424
8425TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8426 // First down on second window.
8427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8429 {150, 50}))
8430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8431
8432 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8433
8434 // Second down on first window.
8435 const MotionEvent secondFingerDownEvent =
8436 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8437 .displayId(ADISPLAY_ID_DEFAULT)
8438 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008439 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8440 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008441 .build();
8442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8443 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8444 InputEventInjectionSync::WAIT_FOR_RESULT))
8445 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8446 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8447
8448 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008449 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008450
8451 // Move on window.
8452 const MotionEvent secondFingerMoveEvent =
8453 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8454 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008455 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8456 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008457 .build();
8458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8459 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8460 InputEventInjectionSync::WAIT_FOR_RESULT));
8461 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8462 mWindow->consumeDragEvent(false, 50, 50);
8463 mSecondWindow->consumeMotionMove();
8464
8465 // Release the drag pointer should perform drop.
8466 const MotionEvent secondFingerUpEvent =
8467 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8468 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008469 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8470 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008471 .build();
8472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8473 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8474 InputEventInjectionSync::WAIT_FOR_RESULT));
8475 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8476 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8477 mWindow->assertNoEvents();
8478 mSecondWindow->consumeMotionMove();
8479}
8480
Arthur Hung3915c1f2022-05-31 07:17:17 +00008481TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008482 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008483
8484 // Update window of second display.
8485 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008486 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008487 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8488
8489 // Let second display has a touch state.
8490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8491 injectMotionEvent(mDispatcher,
8492 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8493 AINPUT_SOURCE_TOUCHSCREEN)
8494 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008495 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008496 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008497 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008498 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008499 // Update window again.
8500 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8501
8502 // Move on window.
8503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8504 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8505 ADISPLAY_ID_DEFAULT, {50, 50}))
8506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8507 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8508 mWindow->consumeDragEvent(false, 50, 50);
8509 mSecondWindow->assertNoEvents();
8510
8511 // Move to another window.
8512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8513 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8514 ADISPLAY_ID_DEFAULT, {150, 50}))
8515 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8516 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8517 mWindow->consumeDragEvent(true, 150, 50);
8518 mSecondWindow->consumeDragEvent(false, 50, 50);
8519
8520 // drop to another window.
8521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8522 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8523 {150, 50}))
8524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8525 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8526 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8527 mWindow->assertNoEvents();
8528 mSecondWindow->assertNoEvents();
8529}
8530
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008531TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8532 startDrag(true, AINPUT_SOURCE_MOUSE);
8533 // Move on window.
8534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8535 injectMotionEvent(mDispatcher,
8536 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8537 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8538 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008539 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008540 .x(50)
8541 .y(50))
8542 .build()))
8543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8544 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8545 mWindow->consumeDragEvent(false, 50, 50);
8546 mSecondWindow->assertNoEvents();
8547
8548 // Move to another window.
8549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8550 injectMotionEvent(mDispatcher,
8551 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8552 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8553 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008554 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008555 .x(150)
8556 .y(50))
8557 .build()))
8558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8559 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8560 mWindow->consumeDragEvent(true, 150, 50);
8561 mSecondWindow->consumeDragEvent(false, 50, 50);
8562
8563 // drop to another window.
8564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8565 injectMotionEvent(mDispatcher,
8566 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8567 .buttonState(0)
8568 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008569 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008570 .x(150)
8571 .y(50))
8572 .build()))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8574 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8575 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8576 mWindow->assertNoEvents();
8577 mSecondWindow->assertNoEvents();
8578}
8579
Vishnu Nair062a8672021-09-03 16:07:44 -07008580class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8581
8582TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8585 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008586 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008587 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8588 window->setFocusable(true);
8589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8590 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008591 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008592
8593 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008594 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008595 window->assertNoEvents();
8596
Prabir Pradhan678438e2023-04-13 19:32:51 +00008597 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8598 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008599 window->assertNoEvents();
8600
8601 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008602 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008603 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8604
Prabir Pradhan678438e2023-04-13 19:32:51 +00008605 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008606 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8607
Prabir Pradhan678438e2023-04-13 19:32:51 +00008608 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8609 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008610 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8611 window->assertNoEvents();
8612}
8613
8614TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8615 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8616 std::make_shared<FakeApplicationHandle>();
8617 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008618 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8619 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008620 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8621 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008622 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008624 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8625 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008626 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008627 window->setOwnerInfo(222, 222);
8628 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8629 window->setFocusable(true);
8630 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8631 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008632 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008633
8634 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008635 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008636 window->assertNoEvents();
8637
Prabir Pradhan678438e2023-04-13 19:32:51 +00008638 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8639 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008640 window->assertNoEvents();
8641
8642 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008643 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8645
Prabir Pradhan678438e2023-04-13 19:32:51 +00008646 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008647 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8648
Prabir Pradhan678438e2023-04-13 19:32:51 +00008649 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8650 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008651 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8652 window->assertNoEvents();
8653}
8654
8655TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8656 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8657 std::make_shared<FakeApplicationHandle>();
8658 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008659 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8660 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008661 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
8662 obscuringWindow->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008663 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008664 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008665 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8666 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008667 window->setDropInputIfObscured(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008668 window->setOwnerInfo(222, 222);
8669 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8670 window->setFocusable(true);
8671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8672 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008673 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008674
8675 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008676 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008677 window->assertNoEvents();
8678
Prabir Pradhan678438e2023-04-13 19:32:51 +00008679 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8680 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008681 window->assertNoEvents();
8682
8683 // When the window is no longer obscured because it went on top, it should get input
8684 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8685
Prabir Pradhan678438e2023-04-13 19:32:51 +00008686 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008687 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8688
Prabir Pradhan678438e2023-04-13 19:32:51 +00008689 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8690 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8692 window->assertNoEvents();
8693}
8694
Antonio Kantekf16f2832021-09-28 04:39:20 +00008695class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8696protected:
8697 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008698 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008699 sp<FakeWindowHandle> mWindow;
8700 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008701 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008702
8703 void SetUp() override {
8704 InputDispatcherTest::SetUp();
8705
8706 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008707 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008708 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008709 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008710 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008711 mSecondWindow =
8712 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008713 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008714 mThirdWindow =
8715 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8716 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8717 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008718
8719 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8721 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8722 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008723 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008724
Antonio Kantek15beb512022-06-13 22:35:41 +00008725 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008726 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008727 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008728 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8729 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008730 mThirdWindow->assertNoEvents();
8731 }
8732
8733 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8734 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008735 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008736 SECOND_DISPLAY_ID)) {
8737 mWindow->assertNoEvents();
8738 mSecondWindow->assertNoEvents();
8739 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008740 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008741 }
8742
Antonio Kantek15beb512022-06-13 22:35:41 +00008743 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, int32_t pid, int32_t uid,
8744 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008745 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8746 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008747 mWindow->consumeTouchModeEvent(inTouchMode);
8748 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008749 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008750 }
8751};
8752
Antonio Kantek26defcf2022-02-08 01:12:27 +00008753TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008754 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008755 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8756 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008757 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008758}
8759
Antonio Kantek26defcf2022-02-08 01:12:27 +00008760TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8761 const WindowInfo& windowInfo = *mWindow->getInfo();
8762 int32_t ownerPid = windowInfo.ownerPid;
8763 int32_t ownerUid = windowInfo.ownerUid;
8764 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
8765 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008766 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008767 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008768 mWindow->assertNoEvents();
8769 mSecondWindow->assertNoEvents();
8770}
8771
8772TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8773 const WindowInfo& windowInfo = *mWindow->getInfo();
8774 int32_t ownerPid = windowInfo.ownerPid;
8775 int32_t ownerUid = windowInfo.ownerUid;
8776 mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
Antonio Kantek15beb512022-06-13 22:35:41 +00008777 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008778 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008779}
8780
Antonio Kantekf16f2832021-09-28 04:39:20 +00008781TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008782 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008783 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8784 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008785 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008786 mWindow->assertNoEvents();
8787 mSecondWindow->assertNoEvents();
8788}
8789
Antonio Kantek15beb512022-06-13 22:35:41 +00008790TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8791 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8792 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8793 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008794 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008795 mWindow->assertNoEvents();
8796 mSecondWindow->assertNoEvents();
8797 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8798}
8799
Antonio Kantek48710e42022-03-24 14:19:30 -07008800TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8801 // Interact with the window first.
8802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8803 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8804 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8805
8806 // Then remove focus.
8807 mWindow->setFocusable(false);
8808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8809
8810 // Assert that caller can switch touch mode by owning one of the last interacted window.
8811 const WindowInfo& windowInfo = *mWindow->getInfo();
8812 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8813 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008814 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008815}
8816
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008817class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8818public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008819 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008820 std::shared_ptr<FakeApplicationHandle> application =
8821 std::make_shared<FakeApplicationHandle>();
8822 std::string name = "Fake Spy ";
8823 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008824 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8825 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008826 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008827 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008828 return spy;
8829 }
8830
8831 sp<FakeWindowHandle> createForeground() {
8832 std::shared_ptr<FakeApplicationHandle> application =
8833 std::make_shared<FakeApplicationHandle>();
8834 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008835 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8836 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008837 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008838 return window;
8839 }
8840
8841private:
8842 int mSpyCount{0};
8843};
8844
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008845using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008846/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008847 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8848 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008849TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8850 ScopedSilentDeath _silentDeath;
8851
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008852 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008853 spy->setTrustedOverlay(false);
8854 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8855 ".* not a trusted overlay");
8856}
8857
8858/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008859 * Input injection into a display with a spy window but no foreground windows should succeed.
8860 */
8861TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008862 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
8864
8865 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8866 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8868 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8869}
8870
8871/**
8872 * Verify the order in which different input windows receive events. The touched foreground window
8873 * (if there is one) should always receive the event first. When there are multiple spy windows, the
8874 * spy windows will receive the event according to their Z-order, where the top-most spy window will
8875 * receive events before ones belows it.
8876 *
8877 * Here, we set up a scenario with four windows in the following Z order from the top:
8878 * spy1, spy2, window, spy3.
8879 * We then inject an event and verify that the foreground "window" receives it first, followed by
8880 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
8881 * window.
8882 */
8883TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
8884 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008885 auto spy1 = createSpy();
8886 auto spy2 = createSpy();
8887 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008888 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
8889 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
8890 const size_t numChannels = channels.size();
8891
Michael Wright8e9a8562022-02-09 13:44:29 +00008892 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008893 if (!epollFd.ok()) {
8894 FAIL() << "Failed to create epoll fd";
8895 }
8896
8897 for (size_t i = 0; i < numChannels; i++) {
8898 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
8899 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
8900 FAIL() << "Failed to add fd to epoll";
8901 }
8902 }
8903
8904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8905 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8907
8908 std::vector<size_t> eventOrder;
8909 std::vector<struct epoll_event> events(numChannels);
8910 for (;;) {
8911 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
8912 (100ms).count());
8913 if (nFds < 0) {
8914 FAIL() << "Failed to call epoll_wait";
8915 }
8916 if (nFds == 0) {
8917 break; // epoll_wait timed out
8918 }
8919 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07008920 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07008921 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008922 channels[i]->consumeMotionDown();
8923 }
8924 }
8925
8926 // Verify the order in which the events were received.
8927 EXPECT_EQ(3u, eventOrder.size());
8928 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
8929 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
8930 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
8931}
8932
8933/**
8934 * A spy window using the NOT_TOUCHABLE flag does not receive events.
8935 */
8936TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
8937 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008938 auto spy = createSpy();
8939 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008940 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8941
8942 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8943 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8945 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8946 spy->assertNoEvents();
8947}
8948
8949/**
8950 * A spy window will only receive gestures that originate within its touchable region. Gestures that
8951 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
8952 * to the window.
8953 */
8954TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
8955 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008956 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008957 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
8958 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8959
8960 // Inject an event outside the spy window's touchable region.
8961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8962 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8964 window->consumeMotionDown();
8965 spy->assertNoEvents();
8966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8967 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
8968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8969 window->consumeMotionUp();
8970 spy->assertNoEvents();
8971
8972 // Inject an event inside the spy window's touchable region.
8973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8975 {5, 10}))
8976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8977 window->consumeMotionDown();
8978 spy->consumeMotionDown();
8979}
8980
8981/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008982 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008983 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008984 */
8985TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
8986 auto window = createForeground();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008987 window->setOwnerInfo(12, 34);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008988 auto spy = createSpy();
8989 spy->setWatchOutsideTouch(true);
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008990 spy->setOwnerInfo(56, 78);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008991 spy->setFrame(Rect{0, 0, 20, 20});
8992 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
8993
8994 // Inject an event outside the spy window's frame and touchable region.
8995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008996 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8997 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8999 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009000 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009001}
9002
9003/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009004 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9005 * pointers that are down within its bounds.
9006 */
9007TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9008 auto windowLeft = createForeground();
9009 windowLeft->setFrame({0, 0, 100, 200});
9010 auto windowRight = createForeground();
9011 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009012 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009013 spy->setFrame({0, 0, 200, 200});
9014 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9015
9016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9017 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9018 {50, 50}))
9019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9020 windowLeft->consumeMotionDown();
9021 spy->consumeMotionDown();
9022
9023 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009024 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009025 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009026 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9027 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009028 .build();
9029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9030 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9031 InputEventInjectionSync::WAIT_FOR_RESULT))
9032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9033 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009034 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009035}
9036
9037/**
9038 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9039 * the spy should receive the second pointer with ACTION_DOWN.
9040 */
9041TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9042 auto window = createForeground();
9043 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009044 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009045 spyRight->setFrame({100, 0, 200, 200});
9046 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9047
9048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9050 {50, 50}))
9051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9052 window->consumeMotionDown();
9053 spyRight->assertNoEvents();
9054
9055 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009056 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009057 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009058 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9059 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009060 .build();
9061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9062 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9063 InputEventInjectionSync::WAIT_FOR_RESULT))
9064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009065 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009066 spyRight->consumeMotionDown();
9067}
9068
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009069/**
9070 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9071 * windows should be allowed to control split touch.
9072 */
9073TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009074 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009075 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009076 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009077 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009078
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009079 auto window = createForeground();
9080 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009081
9082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9083
9084 // First finger down, no window touched.
9085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9086 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9087 {100, 200}))
9088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9089 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9090 window->assertNoEvents();
9091
9092 // Second finger down on window, the window should receive touch down.
9093 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009094 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009095 .displayId(ADISPLAY_ID_DEFAULT)
9096 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009097 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9098 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009099 .build();
9100 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9101 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9102 InputEventInjectionSync::WAIT_FOR_RESULT))
9103 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9104
9105 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009106 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009107}
9108
9109/**
9110 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9111 * do not receive key events.
9112 */
9113TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009114 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009115 spy->setFocusable(false);
9116
9117 auto window = createForeground();
9118 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9119 setFocusedWindow(window);
9120 window->consumeFocusEvent(true);
9121
9122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9123 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9124 window->consumeKeyDown(ADISPLAY_ID_NONE);
9125
9126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9127 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9128 window->consumeKeyUp(ADISPLAY_ID_NONE);
9129
9130 spy->assertNoEvents();
9131}
9132
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009133using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9134
9135/**
9136 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9137 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9138 */
9139TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9140 auto window = createForeground();
9141 auto spy1 = createSpy();
9142 auto spy2 = createSpy();
9143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9144
9145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9146 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9148 window->consumeMotionDown();
9149 spy1->consumeMotionDown();
9150 spy2->consumeMotionDown();
9151
9152 // Pilfer pointers from the second spy window.
9153 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9154 spy2->assertNoEvents();
9155 spy1->consumeMotionCancel();
9156 window->consumeMotionCancel();
9157
9158 // The rest of the gesture should only be sent to the second spy window.
9159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9160 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9161 ADISPLAY_ID_DEFAULT))
9162 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9163 spy2->consumeMotionMove();
9164 spy1->assertNoEvents();
9165 window->assertNoEvents();
9166}
9167
9168/**
9169 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9170 * in the middle of the gesture.
9171 */
9172TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9173 auto window = createForeground();
9174 auto spy = createSpy();
9175 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9176
9177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9178 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9179 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9180 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9181 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9182
9183 window->releaseChannel();
9184
9185 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9186
9187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9188 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9189 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9190 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9191}
9192
9193/**
9194 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9195 * the spy, but not to any other windows.
9196 */
9197TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9198 auto spy = createSpy();
9199 auto window = createForeground();
9200
9201 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9202
9203 // First finger down on the window and the spy.
9204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9205 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9206 {100, 200}))
9207 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9208 spy->consumeMotionDown();
9209 window->consumeMotionDown();
9210
9211 // Spy window pilfers the pointers.
9212 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9213 window->consumeMotionCancel();
9214
9215 // Second finger down on the window and spy, but the window should not receive the pointer down.
9216 const MotionEvent secondFingerDownEvent =
9217 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9218 .displayId(ADISPLAY_ID_DEFAULT)
9219 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009220 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9221 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009222 .build();
9223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9224 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9225 InputEventInjectionSync::WAIT_FOR_RESULT))
9226 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9227
Harry Cutts33476232023-01-30 19:57:29 +00009228 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009229
9230 // Third finger goes down outside all windows, so injection should fail.
9231 const MotionEvent thirdFingerDownEvent =
9232 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9233 .displayId(ADISPLAY_ID_DEFAULT)
9234 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009235 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9236 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9237 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009238 .build();
9239 ASSERT_EQ(InputEventInjectionResult::FAILED,
9240 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9241 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009242 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009243
9244 spy->assertNoEvents();
9245 window->assertNoEvents();
9246}
9247
9248/**
9249 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9250 */
9251TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9252 auto spy = createSpy();
9253 spy->setFrame(Rect(0, 0, 100, 100));
9254 auto window = createForeground();
9255 window->setFrame(Rect(0, 0, 200, 200));
9256
9257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9258
9259 // First finger down on the window only
9260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9261 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9262 {150, 150}))
9263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9264 window->consumeMotionDown();
9265
9266 // Second finger down on the spy and window
9267 const MotionEvent secondFingerDownEvent =
9268 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9269 .displayId(ADISPLAY_ID_DEFAULT)
9270 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009271 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9272 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009273 .build();
9274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9275 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9276 InputEventInjectionSync::WAIT_FOR_RESULT))
9277 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9278 spy->consumeMotionDown();
9279 window->consumeMotionPointerDown(1);
9280
9281 // Third finger down on the spy and window
9282 const MotionEvent thirdFingerDownEvent =
9283 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9284 .displayId(ADISPLAY_ID_DEFAULT)
9285 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009286 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9287 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9288 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009289 .build();
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9291 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9292 InputEventInjectionSync::WAIT_FOR_RESULT))
9293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9294 spy->consumeMotionPointerDown(1);
9295 window->consumeMotionPointerDown(2);
9296
9297 // Spy window pilfers the pointers.
9298 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9299 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9300 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9301
9302 spy->assertNoEvents();
9303 window->assertNoEvents();
9304}
9305
9306/**
9307 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9308 * other windows should be canceled. If this results in the cancellation of all pointers for some
9309 * window, then that window should receive ACTION_CANCEL.
9310 */
9311TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9312 auto spy = createSpy();
9313 spy->setFrame(Rect(0, 0, 100, 100));
9314 auto window = createForeground();
9315 window->setFrame(Rect(0, 0, 200, 200));
9316
9317 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9318
9319 // First finger down on both spy and window
9320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9321 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9322 {10, 10}))
9323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9324 window->consumeMotionDown();
9325 spy->consumeMotionDown();
9326
9327 // Second finger down on the spy and window
9328 const MotionEvent secondFingerDownEvent =
9329 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9330 .displayId(ADISPLAY_ID_DEFAULT)
9331 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009332 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9333 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009334 .build();
9335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9336 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9337 InputEventInjectionSync::WAIT_FOR_RESULT))
9338 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9339 spy->consumeMotionPointerDown(1);
9340 window->consumeMotionPointerDown(1);
9341
9342 // Spy window pilfers the pointers.
9343 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9344 window->consumeMotionCancel();
9345
9346 spy->assertNoEvents();
9347 window->assertNoEvents();
9348}
9349
9350/**
9351 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9352 * be sent to other windows
9353 */
9354TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9355 auto spy = createSpy();
9356 spy->setFrame(Rect(0, 0, 100, 100));
9357 auto window = createForeground();
9358 window->setFrame(Rect(0, 0, 200, 200));
9359
9360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9361
9362 // First finger down on both window and spy
9363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9364 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9365 {10, 10}))
9366 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9367 window->consumeMotionDown();
9368 spy->consumeMotionDown();
9369
9370 // Spy window pilfers the pointers.
9371 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9372 window->consumeMotionCancel();
9373
9374 // Second finger down on the window only
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(10).y(10))
9380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
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 window->consumeMotionDown();
9387 window->assertNoEvents();
9388
9389 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9390 spy->consumeMotionMove();
9391 spy->assertNoEvents();
9392}
9393
Prabir Pradhand65552b2021-10-07 11:23:50 -07009394class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9395public:
9396 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9397 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9398 std::make_shared<FakeApplicationHandle>();
9399 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009400 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9401 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009402 overlay->setFocusable(false);
9403 overlay->setOwnerInfo(111, 111);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009404 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009405 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009406 overlay->setTrustedOverlay(true);
9407
9408 std::shared_ptr<FakeApplicationHandle> application =
9409 std::make_shared<FakeApplicationHandle>();
9410 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009411 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9412 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009413 window->setFocusable(true);
9414 window->setOwnerInfo(222, 222);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009415
9416 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9417 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9418 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009419 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009420 return {std::move(overlay), std::move(window)};
9421 }
9422
9423 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009424 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009425 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009426 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009427 }
9428
9429 void sendStylusEvent(int32_t action) {
9430 NotifyMotionArgs motionArgs =
9431 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9432 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009433 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009434 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009435 }
9436};
9437
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009438using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9439
9440TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9441 ScopedSilentDeath _silentDeath;
9442
Prabir Pradhand65552b2021-10-07 11:23:50 -07009443 auto [overlay, window] = setupStylusOverlayScenario();
9444 overlay->setTrustedOverlay(false);
9445 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9446 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9447 ".* not a trusted overlay");
9448}
9449
9450TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9451 auto [overlay, window] = setupStylusOverlayScenario();
9452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9453
9454 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9455 overlay->consumeMotionDown();
9456 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9457 overlay->consumeMotionUp();
9458
9459 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9460 window->consumeMotionDown();
9461 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9462 window->consumeMotionUp();
9463
9464 overlay->assertNoEvents();
9465 window->assertNoEvents();
9466}
9467
9468TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9469 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009470 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9472
9473 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9474 overlay->consumeMotionDown();
9475 window->consumeMotionDown();
9476 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9477 overlay->consumeMotionUp();
9478 window->consumeMotionUp();
9479
9480 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9481 window->consumeMotionDown();
9482 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9483 window->consumeMotionUp();
9484
9485 overlay->assertNoEvents();
9486 window->assertNoEvents();
9487}
9488
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009489/**
9490 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9491 * The scenario is as follows:
9492 * - The stylus interceptor overlay is configured as a spy window.
9493 * - The stylus interceptor spy receives the start of a new stylus gesture.
9494 * - It pilfers pointers and then configures itself to no longer be a spy.
9495 * - The stylus interceptor continues to receive the rest of the gesture.
9496 */
9497TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9498 auto [overlay, window] = setupStylusOverlayScenario();
9499 overlay->setSpy(true);
9500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9501
9502 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9503 overlay->consumeMotionDown();
9504 window->consumeMotionDown();
9505
9506 // The interceptor pilfers the pointers.
9507 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9508 window->consumeMotionCancel();
9509
9510 // The interceptor configures itself so that it is no longer a spy.
9511 overlay->setSpy(false);
9512 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9513
9514 // It continues to receive the rest of the stylus gesture.
9515 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9516 overlay->consumeMotionMove();
9517 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9518 overlay->consumeMotionUp();
9519
9520 window->assertNoEvents();
9521}
9522
Prabir Pradhan5735a322022-04-11 17:23:34 +00009523struct User {
9524 int32_t mPid;
9525 int32_t mUid;
9526 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9527 std::unique_ptr<InputDispatcher>& mDispatcher;
9528
9529 User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
9530 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9531
9532 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9533 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9534 ADISPLAY_ID_DEFAULT, {100, 200},
9535 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9536 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9537 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9538 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9539 }
9540
9541 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009542 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009543 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009544 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009545 mPolicyFlags);
9546 }
9547
9548 sp<FakeWindowHandle> createWindow() const {
9549 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9550 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009551 sp<FakeWindowHandle> window =
9552 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9553 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009554 window->setOwnerInfo(mPid, mUid);
9555 return window;
9556 }
9557};
9558
9559using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9560
9561TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
9562 auto owner = User(mDispatcher, 10, 11);
9563 auto window = owner.createWindow();
9564 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9565
9566 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9567 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9568 window->consumeMotionDown();
9569
9570 setFocusedWindow(window);
9571 window->consumeFocusEvent(true);
9572
9573 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9574 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9575 window->consumeKeyDown(ADISPLAY_ID_NONE);
9576}
9577
9578TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
9579 auto owner = User(mDispatcher, 10, 11);
9580 auto window = owner.createWindow();
9581 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9582
9583 auto rando = User(mDispatcher, 20, 21);
9584 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9585 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9586
9587 setFocusedWindow(window);
9588 window->consumeFocusEvent(true);
9589
9590 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9591 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9592 window->assertNoEvents();
9593}
9594
9595TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
9596 auto owner = User(mDispatcher, 10, 11);
9597 auto window = owner.createWindow();
9598 auto spy = owner.createWindow();
9599 spy->setSpy(true);
9600 spy->setTrustedOverlay(true);
9601 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9602
9603 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9604 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9605 spy->consumeMotionDown();
9606 window->consumeMotionDown();
9607}
9608
9609TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
9610 auto owner = User(mDispatcher, 10, 11);
9611 auto window = owner.createWindow();
9612
9613 auto rando = User(mDispatcher, 20, 21);
9614 auto randosSpy = rando.createWindow();
9615 randosSpy->setSpy(true);
9616 randosSpy->setTrustedOverlay(true);
9617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9618
9619 // The event is targeted at owner's window, so injection should succeed, but the spy should
9620 // not receive the event.
9621 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9622 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9623 randosSpy->assertNoEvents();
9624 window->consumeMotionDown();
9625}
9626
9627TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
9628 auto owner = User(mDispatcher, 10, 11);
9629 auto window = owner.createWindow();
9630
9631 auto rando = User(mDispatcher, 20, 21);
9632 auto randosSpy = rando.createWindow();
9633 randosSpy->setSpy(true);
9634 randosSpy->setTrustedOverlay(true);
9635 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9636
9637 // A user that has injection permission can inject into any window.
9638 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9639 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9640 ADISPLAY_ID_DEFAULT));
9641 randosSpy->consumeMotionDown();
9642 window->consumeMotionDown();
9643
9644 setFocusedWindow(randosSpy);
9645 randosSpy->consumeFocusEvent(true);
9646
9647 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9648 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9649 window->assertNoEvents();
9650}
9651
9652TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
9653 auto owner = User(mDispatcher, 10, 11);
9654 auto window = owner.createWindow();
9655
9656 auto rando = User(mDispatcher, 20, 21);
9657 auto randosWindow = rando.createWindow();
9658 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9659 randosWindow->setWatchOutsideTouch(true);
9660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9661
9662 // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
9663 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9664 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9665 window->consumeMotionDown();
9666 randosWindow->consumeMotionOutside();
9667}
9668
Garfield Tane84e6f92019-08-29 17:28:41 -07009669} // namespace android::inputdispatcher