blob: 565a27bc68c112b7cc23b020bbea5c2e6a52ad3e [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"
Michael Wrightd02c5b62014-02-10 15:10:22 -080019
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070020#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080021#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080022#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070023#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070024#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000025#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080026#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080027#include <gtest/gtest.h>
Cody Heiner1feacf42023-06-13 15:29:13 -070028#include <input/EventBuilders.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 Pradhane59c6dc2023-06-13 19:53:03 +000098static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000099static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000100
Antonio Kantek15beb512022-06-13 22:35:41 +0000101// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000102static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000103static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000104
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000105// An arbitrary pid of the gesture monitor window
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000106static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000107
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 Pradhane59c6dc2023-06-13 19:53:03 +0000211 struct AnrResult {
212 sp<IBinder> token{};
213 gui::Pid pid{-1};
214 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800215
Michael Wrightd02c5b62014-02-10 15:10:22 -0800216public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000217 FakeInputDispatcherPolicy() = default;
218 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800219
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800220 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700221 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700222 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700223 EXPECT_EQ(event.getDisplayId(), args.displayId);
224
225 const auto& keyEvent = static_cast<const KeyEvent&>(event);
226 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
227 EXPECT_EQ(keyEvent.getAction(), args.action);
228 });
Jackal Guof9696682018-10-05 12:23:23 +0800229 }
230
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700231 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
232 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700233 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700234 EXPECT_EQ(event.getDisplayId(), args.displayId);
235
236 const auto& motionEvent = static_cast<const MotionEvent&>(event);
237 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
238 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000239 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
240 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
241 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
242 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700243 });
Jackal Guof9696682018-10-05 12:23:23 +0800244 }
245
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700246 void assertFilterInputEventWasNotCalled() {
247 std::scoped_lock lock(mLock);
248 ASSERT_EQ(nullptr, mFilteredEvent);
249 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800250
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800251 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700252 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800253 ASSERT_TRUE(mConfigurationChangedTime)
254 << "Timed out waiting for configuration changed call";
255 ASSERT_EQ(*mConfigurationChangedTime, when);
256 mConfigurationChangedTime = std::nullopt;
257 }
258
259 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700260 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800261 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800262 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800263 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
264 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
265 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
266 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
267 mLastNotifySwitch = std::nullopt;
268 }
269
chaviwfd6d3512019-03-25 13:23:49 -0700270 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700271 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800272 ASSERT_EQ(touchedToken, mOnPointerDownToken);
273 mOnPointerDownToken.clear();
274 }
275
276 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700277 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800278 ASSERT_TRUE(mOnPointerDownToken == nullptr)
279 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700280 }
281
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700282 // This function must be called soon after the expected ANR timer starts,
283 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700285 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500286 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800287 std::unique_lock lock(mLock);
288 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500289 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 ASSERT_NO_FATAL_FAILURE(
291 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500292 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700293 }
294
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000295 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800296 const sp<WindowInfoHandle>& window) {
297 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
298 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
299 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500300 }
301
Prabir Pradhanedd96402022-02-15 01:46:16 -0800302 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
303 const sp<IBinder>& expectedToken,
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000304 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800305 std::unique_lock lock(mLock);
306 android::base::ScopedLockAssertion assumeLocked(mLock);
307 AnrResult result;
308 ASSERT_NO_FATAL_FAILURE(result =
309 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000310 ASSERT_EQ(expectedToken, result.token);
311 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500312 }
313
Prabir Pradhanedd96402022-02-15 01:46:16 -0800314 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000315 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500316 std::unique_lock lock(mLock);
317 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800318 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
319 const auto& [token, _] = result;
320 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000321 }
322
Prabir Pradhanedd96402022-02-15 01:46:16 -0800323 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000324 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800325 std::unique_lock lock(mLock);
326 android::base::ScopedLockAssertion assumeLocked(mLock);
327 AnrResult result;
328 ASSERT_NO_FATAL_FAILURE(
329 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000330 ASSERT_EQ(expectedToken, result.token);
331 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800332 }
333
334 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000335 sp<IBinder> getResponsiveWindowToken() {
336 std::unique_lock lock(mLock);
337 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800338 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
339 const auto& [token, _] = result;
340 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700341 }
342
343 void assertNotifyAnrWasNotCalled() {
344 std::scoped_lock lock(mLock);
345 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800346 ASSERT_TRUE(mAnrWindows.empty());
347 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500348 << "ANR was not called, but please also consume the 'connection is responsive' "
349 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700350 }
351
Garfield Tan1c7bc862020-01-28 13:24:04 -0800352 void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
353 mConfig.keyRepeatTimeout = timeout;
354 mConfig.keyRepeatDelay = delay;
355 }
356
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000357 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800358 std::unique_lock lock(mLock);
359 base::ScopedLockAssertion assumeLocked(mLock);
360
361 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
362 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000363 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800364 enabled;
365 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000366 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
367 << ") to be called.";
368 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800369 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000370 auto request = *mPointerCaptureRequest;
371 mPointerCaptureRequest.reset();
372 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800373 }
374
375 void assertSetPointerCaptureNotCalled() {
376 std::unique_lock lock(mLock);
377 base::ScopedLockAssertion assumeLocked(mLock);
378
379 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000380 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800381 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000382 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800383 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000384 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800385 }
386
arthurhungf452d0b2021-01-06 00:19:52 +0800387 void assertDropTargetEquals(const sp<IBinder>& targetToken) {
388 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800389 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800390 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800391 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800392 }
393
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800394 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
395 std::unique_lock lock(mLock);
396 base::ScopedLockAssertion assumeLocked(mLock);
397 std::optional<sp<IBinder>> receivedToken =
398 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
399 mNotifyInputChannelBroken);
400 ASSERT_TRUE(receivedToken.has_value());
401 ASSERT_EQ(token, *receivedToken);
402 }
403
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800404 /**
405 * Set policy timeout. A value of zero means next key will not be intercepted.
406 */
407 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
408 mInterceptKeyTimeout = timeout;
409 }
410
Josep del Riob3981622023-04-18 15:49:45 +0000411 void assertUserActivityPoked() {
412 std::scoped_lock lock(mLock);
413 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
414 }
415
416 void assertUserActivityNotPoked() {
417 std::scoped_lock lock(mLock);
418 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
419 }
420
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000421 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000422 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
423 }
424
425 void assertNotifyDeviceInteractionWasNotCalled() {
426 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
427 }
428
Michael Wrightd02c5b62014-02-10 15:10:22 -0800429private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700430 std::mutex mLock;
431 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
432 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
433 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
434 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800435
Prabir Pradhan99987712020-11-10 18:43:05 -0800436 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000437
438 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800439
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700440 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700441 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800442 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
443 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700444 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800445 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
446 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700447
arthurhungf452d0b2021-01-06 00:19:52 +0800448 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800449 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000450 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800451
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800452 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
453
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000454 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000455
Prabir Pradhanedd96402022-02-15 01:46:16 -0800456 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
457 // for a specific container to become non-empty. When the container is non-empty, return the
458 // first entry from the container and erase it.
459 template <class T>
460 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
461 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
462 // If there is an ANR, Dispatcher won't be idle because there are still events
463 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
464 // before checking if ANR was called.
465 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
466 // to provide it some time to act. 100ms seems reasonable.
467 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
468 const std::chrono::time_point start = std::chrono::steady_clock::now();
469 std::optional<T> token =
470 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
471 if (!token.has_value()) {
472 ADD_FAILURE() << "Did not receive the ANR callback";
473 return {};
474 }
475
476 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
477 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
478 // the dispatcher started counting before this function was called
479 if (std::chrono::abs(timeout - waited) > 100ms) {
480 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
481 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
482 << "ms, but waited "
483 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
484 << "ms instead";
485 }
486 return *token;
487 }
488
489 template <class T>
490 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
491 std::queue<T>& storage,
492 std::unique_lock<std::mutex>& lock,
493 std::condition_variable& condition)
494 REQUIRES(mLock) {
495 condition.wait_for(lock, timeout,
496 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
497 if (storage.empty()) {
498 ADD_FAILURE() << "Did not receive the expected callback";
499 return std::nullopt;
500 }
501 T item = storage.front();
502 storage.pop();
503 return std::make_optional(item);
504 }
505
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600506 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700507 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800508 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800509 }
510
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000511 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800512 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700513 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800514 ASSERT_TRUE(pid.has_value());
515 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700516 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500517 }
518
Prabir Pradhanedd96402022-02-15 01:46:16 -0800519 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000520 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500521 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800522 ASSERT_TRUE(pid.has_value());
523 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500524 mNotifyAnr.notify_all();
525 }
526
527 void notifyNoFocusedWindowAnr(
528 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
529 std::scoped_lock lock(mLock);
530 mAnrApplications.push(applicationHandle);
531 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800532 }
533
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800534 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
535 std::scoped_lock lock(mLock);
536 mBrokenInputChannels.push(connectionToken);
537 mNotifyInputChannelBroken.notify_all();
538 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800539
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600540 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700541
Chris Yef59a2f42020-10-16 12:55:26 -0700542 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
543 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
544 const std::vector<float>& values) override {}
545
546 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
547 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000548
Chris Yefb552902021-02-03 17:18:37 -0800549 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
550
Prabir Pradhana41d2442023-04-20 21:30:40 +0000551 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800552
Prabir Pradhana41d2442023-04-20 21:30:40 +0000553 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700554 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000555 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700556 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000557 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
558 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800559 break;
560 }
561
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700562 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000563 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
564 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800565 break;
566 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700567 default: {
568 ADD_FAILURE() << "Should only filter keys or motions";
569 break;
570 }
Jackal Guof9696682018-10-05 12:23:23 +0800571 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800572 return true;
573 }
574
Prabir Pradhana41d2442023-04-20 21:30:40 +0000575 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
576 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800577 // Clear intercept state when we handled the event.
578 mInterceptKeyTimeout = 0ms;
579 }
580 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800581
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600582 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800585 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
586 // Clear intercept state so we could dispatch the event in next wake.
587 mInterceptKeyTimeout = 0ms;
588 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800589 }
590
Prabir Pradhana41d2442023-04-20 21:30:40 +0000591 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
592 uint32_t) override {
593 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800594 }
595
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600596 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
597 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700598 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800599 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
600 * essentially a passthrough for notifySwitch.
601 */
Harry Cutts33476232023-01-30 19:57:29 +0000602 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800603 }
604
Josep del Riob3981622023-04-18 15:49:45 +0000605 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
606 std::scoped_lock lock(mLock);
607 mPokedUserActivity = true;
608 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800609
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600610 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700611 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700612 mOnPointerDownToken = newToken;
613 }
614
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000615 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800616 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000617 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800618 mPointerCaptureChangedCondition.notify_all();
619 }
620
arthurhungf452d0b2021-01-06 00:19:52 +0800621 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
622 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800623 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800624 mDropTargetWindowToken = token;
625 }
626
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000627 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000628 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000629 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
630 }
631
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700632 void assertFilterInputEventWasCalledInternal(
633 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700634 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800635 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700636 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800637 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800638 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800639};
640
Michael Wrightd02c5b62014-02-10 15:10:22 -0800641// --- InputDispatcherTest ---
642
643class InputDispatcherTest : public testing::Test {
644protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000645 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700646 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000648 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000649 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
650 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800651 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000652 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700653 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800654 }
655
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000656 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700657 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000658 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700659 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700661
662 /**
663 * Used for debugging when writing the test
664 */
665 void dumpDispatcherState() {
666 std::string dump;
667 mDispatcher->dump(dump);
668 std::stringstream ss(dump);
669 std::string to;
670
671 while (std::getline(ss, to, '\n')) {
672 ALOGE("%s", to.c_str());
673 }
674 }
Vishnu Nair958da932020-08-21 17:12:37 -0700675
Chavi Weingarten847e8512023-03-29 00:26:09 +0000676 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700677 FocusRequest request;
678 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000679 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700680 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
681 request.displayId = window->getInfo()->displayId;
682 mDispatcher->setFocusedWindow(request);
683 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800684};
685
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
687 KeyEvent event;
688
689 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800690 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
691 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600692 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
693 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800694 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000695 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000696 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800697 << "Should reject key events with undefined action.";
698
699 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800700 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
701 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600702 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800703 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000704 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000705 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800706 << "Should reject key events with ACTION_MULTIPLE.";
707}
708
709TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
710 MotionEvent event;
711 PointerProperties pointerProperties[MAX_POINTERS + 1];
712 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800713 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714 pointerProperties[i].clear();
715 pointerProperties[i].id = i;
716 pointerCoords[i].clear();
717 }
718
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800719 // Some constants commonly used below
720 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
721 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
722 constexpr int32_t metaState = AMETA_NONE;
723 constexpr MotionClassification classification = MotionClassification::NONE;
724
chaviw9eaa22c2020-07-01 16:21:27 -0700725 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800726 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800727 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700728 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
729 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700730 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
731 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700732 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800733 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000734 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000735 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800736 << "Should reject motion events with undefined action.";
737
738 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800739 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800740 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
741 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
742 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
743 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500744 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800745 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000746 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000747 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800748 << "Should reject motion events with pointer down index too large.";
749
Garfield Tanfbe732e2020-01-24 11:26:14 -0800750 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700751 AMOTION_EVENT_ACTION_POINTER_DOWN |
752 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700753 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
754 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700755 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500756 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000758 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000759 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800760 << "Should reject motion events with pointer down index too small.";
761
762 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800763 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800764 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
765 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
766 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
767 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500768 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800769 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000770 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000771 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800772 << "Should reject motion events with pointer up index too large.";
773
Garfield Tanfbe732e2020-01-24 11:26:14 -0800774 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700775 AMOTION_EVENT_ACTION_POINTER_UP |
776 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700777 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
778 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700779 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500780 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800781 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000782 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000783 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800784 << "Should reject motion events with pointer up index too small.";
785
786 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800787 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
788 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700789 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700790 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
791 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700792 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800793 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000794 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000795 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800796 << "Should reject motion events with 0 pointers.";
797
Garfield Tanfbe732e2020-01-24 11:26:14 -0800798 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
799 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700800 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700801 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
802 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700803 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800804 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000805 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000806 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800807 << "Should reject motion events with more than MAX_POINTERS pointers.";
808
809 // Rejects motion events with invalid pointer ids.
810 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800811 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
812 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700813 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700814 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
815 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700816 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800817 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000818 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000819 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800820 << "Should reject motion events with pointer ids less than 0.";
821
822 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800823 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
824 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700825 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700826 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
827 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700828 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800829 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000830 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000831 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800832 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
833
834 // Rejects motion events with duplicate pointer ids.
835 pointerProperties[0].id = 1;
836 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800837 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
838 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700839 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700840 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
841 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700842 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800843 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000844 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000845 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800846 << "Should reject motion events with duplicate pointer ids.";
847}
848
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800849/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
850
851TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
852 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000853 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800854 ASSERT_TRUE(mDispatcher->waitForIdle());
855
856 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
857}
858
859TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000860 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
861 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000862 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800863
864 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
865 args.policyFlags |= POLICY_FLAG_TRUSTED;
866 mFakePolicy->assertNotifySwitchWasCalled(args);
867}
868
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700869namespace {
870
Arthur Hungb92218b2018-08-14 12:00:21 +0800871// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700872static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700873// Default input dispatching timeout if there is no focused application or paused window
874// from which to determine an appropriate dispatching timeout.
875static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
876 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
877 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800878
879class FakeApplicationHandle : public InputApplicationHandle {
880public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700881 FakeApplicationHandle() {
882 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700883 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500884 mInfo.dispatchingTimeoutMillis =
885 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700886 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800887 virtual ~FakeApplicationHandle() {}
888
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000889 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700890
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500891 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
892 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700893 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800894};
895
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800896class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800897public:
Garfield Tan15601662020-09-22 15:32:38 -0700898 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800899 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700900 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800901 }
902
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800903 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700904 InputEvent* event;
905 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
906 if (!consumeSeq) {
907 return nullptr;
908 }
909 finishEvent(*consumeSeq);
910 return event;
911 }
912
913 /**
914 * Receive an event without acknowledging it.
915 * Return the sequence number that could later be used to send finished signal.
916 */
917 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800918 uint32_t consumeSeq;
919 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800920
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800921 std::chrono::time_point start = std::chrono::steady_clock::now();
922 status_t status = WOULD_BLOCK;
923 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000924 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800925 &event);
926 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
927 if (elapsed > 100ms) {
928 break;
929 }
930 }
931
932 if (status == WOULD_BLOCK) {
933 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700934 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800935 }
936
937 if (status != OK) {
938 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700939 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800940 }
941 if (event == nullptr) {
942 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700943 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800944 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700945 if (outEvent != nullptr) {
946 *outEvent = event;
947 }
948 return consumeSeq;
949 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700951 /**
952 * To be used together with "receiveEvent" to complete the consumption of an event.
953 */
954 void finishEvent(uint32_t consumeSeq) {
955 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
956 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800957 }
958
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000959 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
960 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
961 ASSERT_EQ(OK, status);
962 }
963
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000965 std::optional<int32_t> expectedDisplayId,
966 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800967 InputEvent* event = consume();
968
969 ASSERT_NE(nullptr, event) << mName.c_str()
970 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
973 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800974
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975 if (expectedDisplayId.has_value()) {
976 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
977 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800981 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
982 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedFlags.has_value()) {
984 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986 break;
987 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800989 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000990 assertMotionAction(expectedAction, motionEvent.getAction());
991
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000992 if (expectedFlags.has_value()) {
993 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
994 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800995 break;
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100998 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
999 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001000 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001001 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1002 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001003 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001004 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1005 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001006 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001007 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1008 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001009 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001010 }
1011
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001012 MotionEvent* consumeMotion() {
1013 InputEvent* event = consume();
1014
1015 if (event == nullptr) {
1016 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1017 return nullptr;
1018 }
1019
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001020 if (event->getType() != InputEventType::MOTION) {
1021 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001022 return nullptr;
1023 }
1024 return static_cast<MotionEvent*>(event);
1025 }
1026
1027 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1028 MotionEvent* motionEvent = consumeMotion();
1029 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1030 ASSERT_THAT(*motionEvent, matcher);
1031 }
1032
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001033 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1034 InputEvent* event = consume();
1035 ASSERT_NE(nullptr, event) << mName.c_str()
1036 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001037 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1038 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001039
1040 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1041 << mName.c_str() << ": event displayId should always be NONE.";
1042
1043 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1044 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001045 }
1046
Prabir Pradhan99987712020-11-10 18:43:05 -08001047 void consumeCaptureEvent(bool hasCapture) {
1048 const InputEvent* event = consume();
1049 ASSERT_NE(nullptr, event) << mName.c_str()
1050 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001051 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1052 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001053
1054 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1055 << mName.c_str() << ": event displayId should always be NONE.";
1056
1057 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1058 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1059 }
1060
arthurhungb89ccb02020-12-30 16:19:01 +08001061 void consumeDragEvent(bool isExiting, float x, float y) {
1062 const InputEvent* event = consume();
1063 ASSERT_NE(nullptr, event) << mName.c_str()
1064 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001065 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001066
1067 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1068 << mName.c_str() << ": event displayId should always be NONE.";
1069
1070 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1071 EXPECT_EQ(isExiting, dragEvent.isExiting());
1072 EXPECT_EQ(x, dragEvent.getX());
1073 EXPECT_EQ(y, dragEvent.getY());
1074 }
1075
Antonio Kantekf16f2832021-09-28 04:39:20 +00001076 void consumeTouchModeEvent(bool inTouchMode) {
1077 const InputEvent* event = consume();
1078 ASSERT_NE(nullptr, event) << mName.c_str()
1079 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001080 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1081 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001082
1083 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1084 << mName.c_str() << ": event displayId should always be NONE.";
1085 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1086 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1087 }
1088
chaviwd1c23182019-12-20 18:44:56 -08001089 void assertNoEvents() {
1090 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001091 if (event == nullptr) {
1092 return;
1093 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001094 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001095 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1096 ADD_FAILURE() << "Received key event "
1097 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001098 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001099 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1100 ADD_FAILURE() << "Received motion event "
1101 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001103 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1104 ADD_FAILURE() << "Received focus event, hasFocus = "
1105 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001106 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001107 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1108 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1109 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001110 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001111 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1112 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1113 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001114 }
1115 FAIL() << mName.c_str()
1116 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001117 }
1118
1119 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1120
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001121 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1122
chaviwd1c23182019-12-20 18:44:56 -08001123protected:
1124 std::unique_ptr<InputConsumer> mConsumer;
1125 PreallocatedInputEventFactory mEventFactory;
1126
1127 std::string mName;
1128};
1129
chaviw3277faf2021-05-19 16:45:23 -05001130class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001131public:
1132 static const int32_t WIDTH = 600;
1133 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001134
Chris Yea209fde2020-07-22 13:54:51 -07001135 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001136 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001137 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001138 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001139 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001140 base::Result<std::unique_ptr<InputChannel>> channel =
1141 dispatcher->createInputChannel(name);
1142 token = (*channel)->getConnectionToken();
1143 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001144 }
1145
1146 inputApplicationHandle->updateInfo();
1147 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1148
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001149 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001150 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001151 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001152 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001153 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001154 mInfo.frameLeft = 0;
1155 mInfo.frameTop = 0;
1156 mInfo.frameRight = WIDTH;
1157 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001158 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001159 mInfo.globalScaleFactor = 1.0;
1160 mInfo.touchableRegion.clear();
1161 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001162 mInfo.ownerPid = WINDOW_PID;
1163 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001164 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001165 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001166 }
1167
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001168 sp<FakeWindowHandle> clone(int32_t displayId) {
1169 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1170 handle->mInfo = mInfo;
1171 handle->mInfo.displayId = displayId;
1172 handle->mInfo.id = sId++;
1173 handle->mInputReceiver = mInputReceiver;
1174 return handle;
1175 }
1176
1177 /**
1178 * This is different from clone, because clone will make a "mirror" window - a window with the
1179 * same token, but a different ID. The original window and the clone window are allowed to be
1180 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1181 * This function will create a different object of WindowInfoHandle, but with the same
1182 * properties as the original object - including the ID.
1183 * You can use either the old or the new object to consume the events.
1184 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1185 * at the same time inside dispatcher.
1186 */
1187 sp<FakeWindowHandle> duplicate() {
1188 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1189 handle->mInfo = mInfo;
1190 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001191 return handle;
1192 }
1193
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001194 void setTouchable(bool touchable) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1196 }
chaviwd1c23182019-12-20 18:44:56 -08001197
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001198 void setFocusable(bool focusable) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1200 }
1201
1202 void setVisible(bool visible) {
1203 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1204 }
Vishnu Nair958da932020-08-21 17:12:37 -07001205
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001206 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001207 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001208 }
1209
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001210 void setPaused(bool paused) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1212 }
1213
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001214 void setPreventSplitting(bool preventSplitting) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001216 }
1217
1218 void setSlippery(bool slippery) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1220 }
1221
1222 void setWatchOutsideTouch(bool watchOutside) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1224 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001225
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001226 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1227
1228 void setInterceptsStylus(bool interceptsStylus) {
1229 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1230 }
1231
1232 void setDropInput(bool dropInput) {
1233 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1234 }
1235
1236 void setDropInputIfObscured(bool dropInputIfObscured) {
1237 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1238 }
1239
1240 void setNoInputChannel(bool noInputChannel) {
1241 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1242 }
1243
Josep del Riob3981622023-04-18 15:49:45 +00001244 void setDisableUserActivity(bool disableUserActivity) {
1245 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1246 }
1247
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001248 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1249
chaviw3277faf2021-05-19 16:45:23 -05001250 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001251
Bernardo Rufino7393d172021-02-26 13:56:11 +00001252 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1253
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001254 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001255 mInfo.frameLeft = frame.left;
1256 mInfo.frameTop = frame.top;
1257 mInfo.frameRight = frame.right;
1258 mInfo.frameBottom = frame.bottom;
1259 mInfo.touchableRegion.clear();
1260 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001261
1262 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1263 ui::Transform translate;
1264 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1265 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001266 }
1267
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001268 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1269
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001270 void setIsWallpaper(bool isWallpaper) {
1271 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1272 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001273
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001274 void setDupTouchToWallpaper(bool hasWallpaper) {
1275 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1276 }
chaviwd1c23182019-12-20 18:44:56 -08001277
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001278 void setTrustedOverlay(bool trustedOverlay) {
1279 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1280 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001281
chaviw9eaa22c2020-07-01 16:21:27 -07001282 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1283 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1284 }
1285
1286 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001287
yunho.shinf4a80b82020-11-16 21:13:57 +09001288 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1289
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001290 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001291 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001292 }
1293
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001294 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001295 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001296 }
1297
Svet Ganov5d3bc372020-01-26 23:11:07 -08001298 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001299 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001300 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1301 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001302 }
1303
1304 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001305 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001306 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1307 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308 }
1309
1310 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001311 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001312 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1313 }
1314
1315 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1316 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001317 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001318 expectedFlags);
1319 }
1320
Svet Ganov5d3bc372020-01-26 23:11:07 -08001321 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001322 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1323 int32_t expectedFlags = 0) {
1324 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1325 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001327 }
1328
1329 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001330 int32_t expectedFlags = 0) {
1331 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1332 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001333 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001334 }
1335
1336 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001337 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001338 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001339 expectedFlags);
1340 }
1341
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001342 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1343 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001344 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001345 expectedFlags);
1346 }
1347
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001348 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1349 int32_t expectedFlags = 0) {
1350 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001351 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001352 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001353 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1354 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1355 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1356 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1357 }
1358
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001359 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1360 ASSERT_NE(mInputReceiver, nullptr)
1361 << "Cannot consume events from a window with no receiver";
1362 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1363 }
1364
Prabir Pradhan99987712020-11-10 18:43:05 -08001365 void consumeCaptureEvent(bool hasCapture) {
1366 ASSERT_NE(mInputReceiver, nullptr)
1367 << "Cannot consume events from a window with no receiver";
1368 mInputReceiver->consumeCaptureEvent(hasCapture);
1369 }
1370
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001371 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1372 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001373 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001374 ASSERT_THAT(*motionEvent, matcher);
1375 }
1376
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001377 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001378 std::optional<int32_t> expectedDisplayId,
1379 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001380 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1381 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1382 expectedFlags);
1383 }
1384
arthurhungb89ccb02020-12-30 16:19:01 +08001385 void consumeDragEvent(bool isExiting, float x, float y) {
1386 mInputReceiver->consumeDragEvent(isExiting, x, y);
1387 }
1388
Antonio Kantekf16f2832021-09-28 04:39:20 +00001389 void consumeTouchModeEvent(bool inTouchMode) {
1390 ASSERT_NE(mInputReceiver, nullptr)
1391 << "Cannot consume events from a window with no receiver";
1392 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1393 }
1394
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001395 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001396 if (mInputReceiver == nullptr) {
1397 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1398 return std::nullopt;
1399 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001400 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001401 }
1402
1403 void finishEvent(uint32_t sequenceNum) {
1404 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1405 mInputReceiver->finishEvent(sequenceNum);
1406 }
1407
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001408 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1409 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1410 mInputReceiver->sendTimeline(inputEventId, timeline);
1411 }
1412
chaviwaf87b3e2019-10-01 16:59:28 -07001413 InputEvent* consume() {
1414 if (mInputReceiver == nullptr) {
1415 return nullptr;
1416 }
1417 return mInputReceiver->consume();
1418 }
1419
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001420 MotionEvent* consumeMotion() {
1421 InputEvent* event = consume();
1422 if (event == nullptr) {
1423 ADD_FAILURE() << "Consume failed : no event";
1424 return nullptr;
1425 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001426 if (event->getType() != InputEventType::MOTION) {
1427 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001428 return nullptr;
1429 }
1430 return static_cast<MotionEvent*>(event);
1431 }
1432
Arthur Hungb92218b2018-08-14 12:00:21 +08001433 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001434 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001435 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001436 return; // Can't receive events if the window does not have input channel
1437 }
1438 ASSERT_NE(nullptr, mInputReceiver)
1439 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001440 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001441 }
1442
chaviwaf87b3e2019-10-01 16:59:28 -07001443 sp<IBinder> getToken() { return mInfo.token; }
1444
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001445 const std::string& getName() { return mName; }
1446
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001447 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001448 mInfo.ownerPid = ownerPid;
1449 mInfo.ownerUid = ownerUid;
1450 }
1451
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001452 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001453
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001454 void destroyReceiver() { mInputReceiver = nullptr; }
1455
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001456 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1457
chaviwd1c23182019-12-20 18:44:56 -08001458private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001459 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001460 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001461 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001462 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001463 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001464};
1465
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001466std::atomic<int32_t> FakeWindowHandle::sId{1};
1467
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001468static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001469 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001470 int32_t displayId = ADISPLAY_ID_NONE,
1471 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001472 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001473 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001474 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001475 KeyEvent event;
1476 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1477
1478 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001479 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001480 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1481 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001482
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001483 if (!allowKeyRepeat) {
1484 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1485 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001486 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001487 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001488}
1489
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001490static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001491 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001492 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001493}
1494
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001495// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1496// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1497// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001498static InputEventInjectionResult injectKeyDownNoRepeat(
1499 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001500 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001501 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001502 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001503}
1504
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001505static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001506 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001507 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001508}
1509
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001510static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001511 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001512 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001513 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001514 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001515 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1516 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001517}
1518
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001519static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001520 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001521 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001522 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001523 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1524 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001525 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001526 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001527 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001528 MotionEventBuilder motionBuilder =
1529 MotionEventBuilder(action, source)
1530 .displayId(displayId)
1531 .eventTime(eventTime)
1532 .rawXCursorPosition(cursorPosition.x)
1533 .rawYCursorPosition(cursorPosition.y)
1534 .pointer(
1535 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1536 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1537 motionBuilder.downTime(eventTime);
1538 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001539
1540 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001541 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1542 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001543}
1544
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001545static InputEventInjectionResult injectMotionDown(
1546 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1547 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001548 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001549}
1550
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001551static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001552 int32_t source, int32_t displayId,
1553 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001554 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001555}
1556
Jackal Guof9696682018-10-05 12:23:23 +08001557static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1558 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1559 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001560 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001561 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1562 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001563
1564 return args;
1565}
1566
Josep del Riob3981622023-04-18 15:49:45 +00001567static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1568 int32_t displayId = ADISPLAY_ID_NONE) {
1569 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1570 // Define a valid key event.
1571 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1572 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1573 currentTime);
1574
1575 return args;
1576}
1577
1578static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1579 int32_t displayId = ADISPLAY_ID_NONE) {
1580 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1581 // Define a valid key event.
1582 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1583 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1584 AMETA_NONE, currentTime);
1585
1586 return args;
1587}
1588
Prabir Pradhan678438e2023-04-13 19:32:51 +00001589[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1590 int32_t displayId,
1591 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001592 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001593 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1594 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1595 }
1596
chaviwd1c23182019-12-20 18:44:56 -08001597 PointerProperties pointerProperties[pointerCount];
1598 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001599
chaviwd1c23182019-12-20 18:44:56 -08001600 for (size_t i = 0; i < pointerCount; i++) {
1601 pointerProperties[i].clear();
1602 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001603 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001604
chaviwd1c23182019-12-20 18:44:56 -08001605 pointerCoords[i].clear();
1606 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1607 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1608 }
Jackal Guof9696682018-10-05 12:23:23 +08001609
1610 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1611 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001612 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001613 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1614 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001615 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1616 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001617 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1618 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001619
1620 return args;
1621}
1622
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001623static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1624 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1625}
1626
chaviwd1c23182019-12-20 18:44:56 -08001627static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1628 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1629}
1630
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001631static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1632 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001633 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001634}
1635
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001636} // namespace
1637
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001638/**
1639 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1640 * broken channel.
1641 */
1642TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1643 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1644 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001645 sp<FakeWindowHandle>::make(application, mDispatcher,
1646 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001647
1648 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1649
1650 // Window closes its channel, but the window remains.
1651 window->destroyReceiver();
1652 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1653}
1654
Arthur Hungb92218b2018-08-14 12:00:21 +08001655TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001657 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1658 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001659
Arthur Hung72d8dc32020-03-28 00:48:39 +00001660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1662 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001664
1665 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001666 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001667}
1668
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001669TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1670 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);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001673
1674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1675 // Inject a MotionEvent to an unknown display.
1676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1677 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1679
1680 // Window should receive motion event.
1681 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1682}
1683
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001684/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001685 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001686 * This test serves as a sanity check for the next test, where setInputWindows is
1687 * called twice.
1688 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001689TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001690 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001691 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1692 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001694
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
1705/**
1706 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001707 */
1708TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1711 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001712 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713
1714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1715 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001717 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1718 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001720
1721 // Window should receive motion event.
1722 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1723}
1724
Arthur Hungb92218b2018-08-14 12:00:21 +08001725// The foreground window should receive the first touch down event.
1726TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001728 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001730 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001731 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001732
Arthur Hung72d8dc32020-03-28 00:48:39 +00001733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1735 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001737
1738 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001739 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001740 windowSecond->assertNoEvents();
1741}
1742
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001743/**
1744 * Two windows: A top window, and a wallpaper behind the window.
1745 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1746 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001747 * 1. foregroundWindow <-- dup touch to wallpaper
1748 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001749 */
1750TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1752 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001753 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001754 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001755 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001756 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001757 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001758
1759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1761 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1762 {100, 200}))
1763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1764
1765 // Both foreground window and its wallpaper should receive the touch down
1766 foregroundWindow->consumeMotionDown();
1767 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1768
1769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1770 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1771 ADISPLAY_ID_DEFAULT, {110, 200}))
1772 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1773
1774 foregroundWindow->consumeMotionMove();
1775 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1776
1777 // Now the foreground window goes away, but the wallpaper stays
1778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1779 foregroundWindow->consumeMotionCancel();
1780 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1781 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1782}
1783
1784/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001785 * Two fingers down on the window, and lift off the first finger.
1786 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1787 * contains a single pointer.
1788 */
1789TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1790 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1791 sp<FakeWindowHandle> window =
1792 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1793
1794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001795 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1797 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1798 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001799 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001800 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1801 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1802 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1803 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001804 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001805 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1806 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1807 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1808 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001809 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1810 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1811 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1812
1813 // Remove the window. The gesture should be canceled
1814 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1815 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1816 window->consumeMotionEvent(
1817 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1818}
1819
1820/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001821 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1822 * with the following differences:
1823 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1824 * clean up the connection.
1825 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1826 * Ensure that there's no crash in the dispatcher.
1827 */
1828TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1830 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001831 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001832 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001833 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001834 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001835 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001836
1837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1839 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1840 {100, 200}))
1841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1842
1843 // Both foreground window and its wallpaper should receive the touch down
1844 foregroundWindow->consumeMotionDown();
1845 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1846
1847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1848 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1849 ADISPLAY_ID_DEFAULT, {110, 200}))
1850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1851
1852 foregroundWindow->consumeMotionMove();
1853 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1854
1855 // Wallpaper closes its channel, but the window remains.
1856 wallpaperWindow->destroyReceiver();
1857 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1858
1859 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1860 // is no longer valid.
1861 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1862 foregroundWindow->consumeMotionCancel();
1863}
1864
Arthur Hungc539dbb2022-12-08 07:45:36 +00001865class ShouldSplitTouchFixture : public InputDispatcherTest,
1866 public ::testing::WithParamInterface<bool> {};
1867INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1868 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001869/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001870 * A single window that receives touch (on top), and a wallpaper window underneath it.
1871 * The top window gets a multitouch gesture.
1872 * Ensure that wallpaper gets the same gesture.
1873 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001874TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001876 sp<FakeWindowHandle> foregroundWindow =
1877 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1878 foregroundWindow->setDupTouchToWallpaper(true);
1879 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001880
1881 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001882 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001883 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884
Arthur Hungc539dbb2022-12-08 07:45:36 +00001885 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001886
1887 // Touch down on top window
1888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1889 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1890 {100, 100}))
1891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1892
1893 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001894 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001895 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1896
1897 // Second finger down on the top window
1898 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001899 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001901 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1902 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001903 .build();
1904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1905 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1906 InputEventInjectionSync::WAIT_FOR_RESULT))
1907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1908
Harry Cutts33476232023-01-30 19:57:29 +00001909 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1910 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001911 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001912
1913 const MotionEvent secondFingerUpEvent =
1914 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1915 .displayId(ADISPLAY_ID_DEFAULT)
1916 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001917 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1918 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001919 .build();
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1921 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1922 InputEventInjectionSync::WAIT_FOR_RESULT))
1923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1924 foregroundWindow->consumeMotionPointerUp(0);
1925 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1926
1927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001928 injectMotionEvent(mDispatcher,
1929 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1930 AINPUT_SOURCE_TOUCHSCREEN)
1931 .displayId(ADISPLAY_ID_DEFAULT)
1932 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1933 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001934 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001935 .x(100)
1936 .y(100))
1937 .build(),
1938 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001939 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1940 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1941 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001942}
1943
1944/**
1945 * Two windows: a window on the left and window on the right.
1946 * A third window, wallpaper, is behind both windows, and spans both top windows.
1947 * The first touch down goes to the left window. A second pointer touches down on the right window.
1948 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1949 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1950 * ACTION_POINTER_DOWN(1).
1951 */
1952TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1954 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001955 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001956 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001957 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958
1959 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001960 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001961 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001962 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963
1964 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001965 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001966 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001967 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968
1969 mDispatcher->setInputWindows(
1970 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1971
1972 // Touch down on left window
1973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1975 {100, 100}))
1976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1977
1978 // Both foreground window and its wallpaper should receive the touch down
1979 leftWindow->consumeMotionDown();
1980 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1981
1982 // Second finger down on the right window
1983 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001984 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001985 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001986 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1987 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 .build();
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1990 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1991 InputEventInjectionSync::WAIT_FOR_RESULT))
1992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1993
1994 leftWindow->consumeMotionMove();
1995 // Since the touch is split, right window gets ACTION_DOWN
1996 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001997 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001998 expectedWallpaperFlags);
1999
2000 // Now, leftWindow, which received the first finger, disappears.
2001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2002 leftWindow->consumeMotionCancel();
2003 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2004 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2005
2006 // The pointer that's still down on the right window moves, and goes to the right window only.
2007 // As far as the dispatcher's concerned though, both pointers are still present.
2008 const MotionEvent secondFingerMoveEvent =
2009 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2010 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002011 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2012 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013 .build();
2014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2015 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2016 InputEventInjectionSync::WAIT_FOR_RESULT));
2017 rightWindow->consumeMotionMove();
2018
2019 leftWindow->assertNoEvents();
2020 rightWindow->assertNoEvents();
2021 wallpaperWindow->assertNoEvents();
2022}
2023
Arthur Hungc539dbb2022-12-08 07:45:36 +00002024/**
2025 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2026 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2027 * The right window should receive ACTION_DOWN.
2028 */
2029TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002030 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002031 sp<FakeWindowHandle> leftWindow =
2032 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2033 leftWindow->setFrame(Rect(0, 0, 200, 200));
2034 leftWindow->setDupTouchToWallpaper(true);
2035 leftWindow->setSlippery(true);
2036
2037 sp<FakeWindowHandle> rightWindow =
2038 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2039 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002040
2041 sp<FakeWindowHandle> wallpaperWindow =
2042 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2043 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002044
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045 mDispatcher->setInputWindows(
2046 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002047
Arthur Hungc539dbb2022-12-08 07:45:36 +00002048 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2050 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002051 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002053
2054 // Both foreground window and its wallpaper should receive the touch down
2055 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002056 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2057
Arthur Hungc539dbb2022-12-08 07:45:36 +00002058 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002060 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2061 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2063
Arthur Hungc539dbb2022-12-08 07:45:36 +00002064 leftWindow->consumeMotionCancel();
2065 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2066 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002067}
2068
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002069/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002070 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2071 * interactive, it might stop sending this flag.
2072 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2073 * to have a consistent input stream.
2074 *
2075 * Test procedure:
2076 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2077 * DOWN (new gesture).
2078 *
2079 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2080 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2081 *
2082 * We technically just need a single window here, but we are using two windows (spy on top and a
2083 * regular window below) to emulate the actual situation where it happens on the device.
2084 */
2085TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2086 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2087 sp<FakeWindowHandle> spyWindow =
2088 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2089 spyWindow->setFrame(Rect(0, 0, 200, 200));
2090 spyWindow->setTrustedOverlay(true);
2091 spyWindow->setSpy(true);
2092
2093 sp<FakeWindowHandle> window =
2094 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2095 window->setFrame(Rect(0, 0, 200, 200));
2096
2097 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2098 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002099
2100 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002101 mDispatcher->notifyMotion(
2102 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2103 .deviceId(touchDeviceId)
2104 .policyFlags(DEFAULT_POLICY_FLAGS)
2105 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2106 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002107
Prabir Pradhan678438e2023-04-13 19:32:51 +00002108 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2109 .deviceId(touchDeviceId)
2110 .policyFlags(DEFAULT_POLICY_FLAGS)
2111 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2112 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2113 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002114 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2115 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2116 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2117 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2118
2119 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002120 mDispatcher->notifyMotion(
2121 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2122 .deviceId(touchDeviceId)
2123 .policyFlags(0)
2124 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2125 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2126 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002127 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2128 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2129
2130 // We don't need to reset the device to reproduce the issue, but the reset event typically
2131 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002132 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002133
2134 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002135 mDispatcher->notifyMotion(
2136 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2137 .deviceId(touchDeviceId)
2138 .policyFlags(DEFAULT_POLICY_FLAGS)
2139 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2140 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002141 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2142 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2143
2144 // No more events
2145 spyWindow->assertNoEvents();
2146 window->assertNoEvents();
2147}
2148
2149/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002150 * Two windows: a window on the left and a window on the right.
2151 * Mouse is hovered from the right window into the left window.
2152 * Next, we tap on the left window, where the cursor was last seen.
2153 * The second tap is done onto the right window.
2154 * The mouse and tap are from two different devices.
2155 * We technically don't need to set the downtime / eventtime for these events, but setting these
2156 * explicitly helps during debugging.
2157 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2158 * In the buggy implementation, a tap on the right window would cause a crash.
2159 */
2160TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2162 sp<FakeWindowHandle> leftWindow =
2163 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2164 leftWindow->setFrame(Rect(0, 0, 200, 200));
2165
2166 sp<FakeWindowHandle> rightWindow =
2167 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2168 rightWindow->setFrame(Rect(200, 0, 400, 200));
2169
2170 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2171 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2172 // stale.
2173 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2174 const int32_t mouseDeviceId = 6;
2175 const int32_t touchDeviceId = 4;
2176 // Move the cursor from right
2177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2178 injectMotionEvent(mDispatcher,
2179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2180 AINPUT_SOURCE_MOUSE)
2181 .deviceId(mouseDeviceId)
2182 .downTime(baseTime + 10)
2183 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002184 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002185 .x(300)
2186 .y(100))
2187 .build()));
2188 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2189
2190 // .. to the left window
2191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2192 injectMotionEvent(mDispatcher,
2193 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2194 AINPUT_SOURCE_MOUSE)
2195 .deviceId(mouseDeviceId)
2196 .downTime(baseTime + 10)
2197 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002198 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002199 .x(110)
2200 .y(100))
2201 .build()));
2202 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2203 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2204 // Now tap the left window
2205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2206 injectMotionEvent(mDispatcher,
2207 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2208 AINPUT_SOURCE_TOUCHSCREEN)
2209 .deviceId(touchDeviceId)
2210 .downTime(baseTime + 40)
2211 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002212 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002213 .x(100)
2214 .y(100))
2215 .build()));
2216 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2217 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2218
2219 // release tap
2220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2221 injectMotionEvent(mDispatcher,
2222 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2223 AINPUT_SOURCE_TOUCHSCREEN)
2224 .deviceId(touchDeviceId)
2225 .downTime(baseTime + 40)
2226 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002227 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002228 .x(100)
2229 .y(100))
2230 .build()));
2231 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2232
2233 // Tap the window on the right
2234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2235 injectMotionEvent(mDispatcher,
2236 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2237 AINPUT_SOURCE_TOUCHSCREEN)
2238 .deviceId(touchDeviceId)
2239 .downTime(baseTime + 60)
2240 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002241 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002242 .x(300)
2243 .y(100))
2244 .build()));
2245 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2246
2247 // release tap
2248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2249 injectMotionEvent(mDispatcher,
2250 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2251 AINPUT_SOURCE_TOUCHSCREEN)
2252 .deviceId(touchDeviceId)
2253 .downTime(baseTime + 60)
2254 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002255 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002256 .x(300)
2257 .y(100))
2258 .build()));
2259 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2260
2261 // No more events
2262 leftWindow->assertNoEvents();
2263 rightWindow->assertNoEvents();
2264}
2265
2266/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002267 * Start hovering in a window. While this hover is still active, make another window appear on top.
2268 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2269 * While the top window is present, the hovering is stopped.
2270 * Later, hovering gets resumed again.
2271 * Ensure that new hover gesture is handled correctly.
2272 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2273 * to the window that's currently being hovered over.
2274 */
2275TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2277 sp<FakeWindowHandle> window =
2278 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2279 window->setFrame(Rect(0, 0, 200, 200));
2280
2281 // Only a single window is present at first
2282 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2283
2284 // Start hovering in the window
2285 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2286 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2287 .build());
2288 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2289
2290 // Now, an obscuring window appears!
2291 sp<FakeWindowHandle> obscuringWindow =
2292 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2293 ADISPLAY_ID_DEFAULT,
2294 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2295 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2296 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2297 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2298 obscuringWindow->setNoInputChannel(true);
2299 obscuringWindow->setFocusable(false);
2300 obscuringWindow->setAlpha(1.0);
2301 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2302
2303 // While this new obscuring window is present, the hovering is stopped
2304 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2305 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2306 .build());
2307 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2308
2309 // Now the obscuring window goes away.
2310 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2311
2312 // And a new hover gesture starts.
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
2319/**
2320 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2321 * the obscuring window.
2322 */
2323TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2325 sp<FakeWindowHandle> window =
2326 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2327 window->setFrame(Rect(0, 0, 200, 200));
2328
2329 // Only a single window is present at first
2330 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2331
2332 // Start hovering in the window
2333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2334 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2335 .build());
2336 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2337
2338 // Now, an obscuring window appears!
2339 sp<FakeWindowHandle> obscuringWindow =
2340 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2341 ADISPLAY_ID_DEFAULT,
2342 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2343 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2344 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2345 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2346 obscuringWindow->setNoInputChannel(true);
2347 obscuringWindow->setFocusable(false);
2348 obscuringWindow->setAlpha(1.0);
2349 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2350
2351 // While this new obscuring window is present, the hovering continues. The event can't go to the
2352 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2353 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2354 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2355 .build());
2356 obscuringWindow->assertNoEvents();
2357 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2358
2359 // Now the obscuring window goes away.
2360 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2361
2362 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2363 // so it should generate a HOVER_ENTER
2364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2365 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2366 .build());
2367 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2368
2369 // Now the MOVE should be getting dispatched normally
2370 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2372 .build());
2373 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2374}
2375
2376/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002377 * Two windows: a window on the left and a window on the right.
2378 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2379 * down. Then, on the left window, also place second touch pointer down.
2380 * This test tries to reproduce a crash.
2381 * In the buggy implementation, second pointer down on the left window would cause a crash.
2382 */
2383TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2385 sp<FakeWindowHandle> leftWindow =
2386 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2387 leftWindow->setFrame(Rect(0, 0, 200, 200));
2388
2389 sp<FakeWindowHandle> rightWindow =
2390 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2391 rightWindow->setFrame(Rect(200, 0, 400, 200));
2392
2393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2394
2395 const int32_t touchDeviceId = 4;
2396 const int32_t mouseDeviceId = 6;
2397 NotifyMotionArgs args;
2398
2399 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2401 .deviceId(mouseDeviceId)
2402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2403 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002404 leftWindow->consumeMotionEvent(
2405 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2406
2407 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002408 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2409 .deviceId(mouseDeviceId)
2410 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2411 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2412 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002413
2414 leftWindow->consumeMotionEvent(
2415 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2416 leftWindow->consumeMotionEvent(
2417 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2418
Prabir Pradhan678438e2023-04-13 19:32:51 +00002419 mDispatcher->notifyMotion(
2420 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2421 .deviceId(mouseDeviceId)
2422 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2423 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2424 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2425 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002426 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2427
2428 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2430 .deviceId(touchDeviceId)
2431 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2432 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002433 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2434
2435 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2436
2437 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002438 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2439 .deviceId(touchDeviceId)
2440 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2441 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2442 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002443 leftWindow->consumeMotionEvent(
2444 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2445 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2446 // current implementation.
2447 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2448 rightWindow->consumeMotionEvent(
2449 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2450
2451 leftWindow->assertNoEvents();
2452 rightWindow->assertNoEvents();
2453}
2454
2455/**
2456 * On a single window, use two different devices: mouse and touch.
2457 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2458 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2459 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2460 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2461 * represent a new gesture.
2462 */
2463TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2465 sp<FakeWindowHandle> window =
2466 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2467 window->setFrame(Rect(0, 0, 400, 400));
2468
2469 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2470
2471 const int32_t touchDeviceId = 4;
2472 const int32_t mouseDeviceId = 6;
2473 NotifyMotionArgs args;
2474
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002475 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2477 .deviceId(touchDeviceId)
2478 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2479 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002480 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002481 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2482 .deviceId(touchDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2484 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2485 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002486 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002487 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2488 .deviceId(touchDeviceId)
2489 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2490 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2491 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002492 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2493 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2494 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2495
2496 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2498 .deviceId(mouseDeviceId)
2499 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2500 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2501 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002502
2503 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002504 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002505 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2506
Prabir Pradhan678438e2023-04-13 19:32:51 +00002507 mDispatcher->notifyMotion(
2508 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2509 .deviceId(mouseDeviceId)
2510 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2511 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2512 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2513 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002514 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2515
2516 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002517 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2518 .deviceId(touchDeviceId)
2519 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2520 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2521 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002522 // The pointer_down event should be ignored
2523 window->assertNoEvents();
2524}
2525
2526/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002527 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2528 * the injected event.
2529 */
2530TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2532 sp<FakeWindowHandle> window =
2533 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2534 window->setFrame(Rect(0, 0, 400, 400));
2535
2536 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2537
2538 const int32_t touchDeviceId = 4;
2539 NotifyMotionArgs args;
2540 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2541 // completion.
2542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2543 injectMotionEvent(mDispatcher,
2544 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2545 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002546 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002547 .x(50)
2548 .y(50))
2549 .build()));
2550 window->consumeMotionEvent(
2551 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2552
2553 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2554 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2556 .deviceId(touchDeviceId)
2557 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2558 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002559
2560 window->consumeMotionEvent(
2561 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2562 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2563}
2564
2565/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002566 * This test is similar to the test above, but the sequence of injected events is different.
2567 *
2568 * Two windows: a window on the left and a window on the right.
2569 * Mouse is hovered over the left window.
2570 * Next, we tap on the left window, where the cursor was last seen.
2571 *
2572 * After that, we inject one finger down onto the right window, and then a second finger down onto
2573 * the left window.
2574 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2575 * window (first), and then another on the left window (second).
2576 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2577 * In the buggy implementation, second finger down on the left window would cause a crash.
2578 */
2579TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2581 sp<FakeWindowHandle> leftWindow =
2582 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2583 leftWindow->setFrame(Rect(0, 0, 200, 200));
2584
2585 sp<FakeWindowHandle> rightWindow =
2586 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2587 rightWindow->setFrame(Rect(200, 0, 400, 200));
2588
2589 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2590
2591 const int32_t mouseDeviceId = 6;
2592 const int32_t touchDeviceId = 4;
2593 // Hover over the left window. Keep the cursor there.
2594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2595 injectMotionEvent(mDispatcher,
2596 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2597 AINPUT_SOURCE_MOUSE)
2598 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002599 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002600 .x(50)
2601 .y(50))
2602 .build()));
2603 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2604
2605 // Tap on left window
2606 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2607 injectMotionEvent(mDispatcher,
2608 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2609 AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002611 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002612 .x(100)
2613 .y(100))
2614 .build()));
2615
2616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2617 injectMotionEvent(mDispatcher,
2618 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2619 AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002621 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002622 .x(100)
2623 .y(100))
2624 .build()));
2625 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2626 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2628
2629 // First finger down on right window
2630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2631 injectMotionEvent(mDispatcher,
2632 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2633 AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002635 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002636 .x(300)
2637 .y(100))
2638 .build()));
2639 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2640
2641 // Second finger down on the left window
2642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2643 injectMotionEvent(mDispatcher,
2644 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2645 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002646 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002647 .x(300)
2648 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002649 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002650 .x(100)
2651 .y(100))
2652 .build()));
2653 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2654 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2655
2656 // No more events
2657 leftWindow->assertNoEvents();
2658 rightWindow->assertNoEvents();
2659}
2660
2661/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002662 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2663 * While the touch is down, new hover events from the stylus device should be ignored. After the
2664 * touch is gone, stylus hovering should start working again.
2665 */
2666TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2668 sp<FakeWindowHandle> window =
2669 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2670 window->setFrame(Rect(0, 0, 200, 200));
2671
2672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2673
2674 const int32_t stylusDeviceId = 5;
2675 const int32_t touchDeviceId = 4;
2676 // Start hovering with stylus
2677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2678 injectMotionEvent(mDispatcher,
2679 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2680 AINPUT_SOURCE_STYLUS)
2681 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002682 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002683 .x(50)
2684 .y(50))
2685 .build()));
2686 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2687
2688 // Finger down on the window
2689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2690 injectMotionEvent(mDispatcher,
2691 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2692 AINPUT_SOURCE_TOUCHSCREEN)
2693 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002694 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002695 .x(100)
2696 .y(100))
2697 .build()));
2698 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2699 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2700
2701 // Try to continue hovering with stylus. Since we are already down, injection should fail
2702 ASSERT_EQ(InputEventInjectionResult::FAILED,
2703 injectMotionEvent(mDispatcher,
2704 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2705 AINPUT_SOURCE_STYLUS)
2706 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002707 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002708 .x(50)
2709 .y(50))
2710 .build()));
2711 // No event should be sent. This event should be ignored because a pointer from another device
2712 // is already down.
2713
2714 // Lift up the finger
2715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2716 injectMotionEvent(mDispatcher,
2717 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2718 AINPUT_SOURCE_TOUCHSCREEN)
2719 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002720 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002721 .x(100)
2722 .y(100))
2723 .build()));
2724 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2725
2726 // Now that the touch is gone, stylus hovering should start working again
2727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2728 injectMotionEvent(mDispatcher,
2729 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2730 AINPUT_SOURCE_STYLUS)
2731 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002732 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002733 .x(50)
2734 .y(50))
2735 .build()));
2736 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2737 // No more events
2738 window->assertNoEvents();
2739}
2740
2741/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002742 * A spy window above a window with no input channel.
2743 * Start hovering with a stylus device, and then tap with it.
2744 * Ensure spy window receives the entire sequence.
2745 */
2746TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2748 sp<FakeWindowHandle> spyWindow =
2749 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2750 spyWindow->setFrame(Rect(0, 0, 200, 200));
2751 spyWindow->setTrustedOverlay(true);
2752 spyWindow->setSpy(true);
2753 sp<FakeWindowHandle> window =
2754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2755 window->setNoInputChannel(true);
2756 window->setFrame(Rect(0, 0, 200, 200));
2757
2758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2759
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002760 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2762 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2763 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002764 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2765 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2767 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2768 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002769 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2770
2771 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2773 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002775 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2776
2777 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2779 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2780 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002781 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2782
2783 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2785 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2786 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002787 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2788 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2790 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2791 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002792 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2793
2794 // No more events
2795 spyWindow->assertNoEvents();
2796 window->assertNoEvents();
2797}
2798
2799/**
2800 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2801 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2802 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2803 * While the mouse is down, new move events from the touch device should be ignored.
2804 */
2805TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2807 sp<FakeWindowHandle> spyWindow =
2808 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2809 spyWindow->setFrame(Rect(0, 0, 200, 200));
2810 spyWindow->setTrustedOverlay(true);
2811 spyWindow->setSpy(true);
2812 sp<FakeWindowHandle> window =
2813 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2814 window->setFrame(Rect(0, 0, 200, 200));
2815
2816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2817
2818 const int32_t mouseDeviceId = 7;
2819 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002820
2821 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2823 .deviceId(mouseDeviceId)
2824 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2825 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002826 spyWindow->consumeMotionEvent(
2827 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2828 window->consumeMotionEvent(
2829 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2830
2831 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2835 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002836 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2837 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2838 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2839 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2840
Prabir Pradhan678438e2023-04-13 19:32:51 +00002841 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2842 .deviceId(touchDeviceId)
2843 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2844 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002845 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2846 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2847
2848 // Pilfer the stream
2849 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2850 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2851
Prabir Pradhan678438e2023-04-13 19:32:51 +00002852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2853 .deviceId(touchDeviceId)
2854 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2855 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002856 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2857
2858 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2860 .deviceId(mouseDeviceId)
2861 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2862 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2863 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002864
2865 spyWindow->consumeMotionEvent(
2866 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2867 spyWindow->consumeMotionEvent(
2868 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2869 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2870
Prabir Pradhan678438e2023-04-13 19:32:51 +00002871 mDispatcher->notifyMotion(
2872 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2873 .deviceId(mouseDeviceId)
2874 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2875 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2876 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2877 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002878 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2879 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2880
2881 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2883 .deviceId(mouseDeviceId)
2884 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2885 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2886 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002887 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2888 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2889
2890 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2892 .deviceId(touchDeviceId)
2893 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2894 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002895
2896 // No more events
2897 spyWindow->assertNoEvents();
2898 window->assertNoEvents();
2899}
2900
2901/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002902 * On the display, have a single window, and also an area where there's no window.
2903 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2904 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2905 */
2906TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2908 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002909 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002910
2911 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002912
2913 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002914 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002915
2916 mDispatcher->waitForIdle();
2917 window->assertNoEvents();
2918
2919 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002920 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002921 mDispatcher->waitForIdle();
2922 window->consumeMotionDown();
2923}
2924
2925/**
2926 * Same test as above, but instead of touching the empty space, the first touch goes to
2927 * non-touchable window.
2928 */
2929TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2931 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002932 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002933 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2934 window1->setTouchable(false);
2935 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002936 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002937 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2938
2939 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2940
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002941 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002942 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002943
2944 mDispatcher->waitForIdle();
2945 window1->assertNoEvents();
2946 window2->assertNoEvents();
2947
2948 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002949 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002950 mDispatcher->waitForIdle();
2951 window2->consumeMotionDown();
2952}
2953
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002954/**
2955 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2956 * to the event time of the first ACTION_DOWN sent to the particular window.
2957 */
2958TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2960 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002961 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002962 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2963 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002964 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2966
2967 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2968
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002969 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002970 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002971
2972 mDispatcher->waitForIdle();
2973 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002974 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002975 window2->assertNoEvents();
2976 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2977 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2978 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2979
2980 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002981 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002982 mDispatcher->waitForIdle();
2983 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002984 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002985 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2986 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2987 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2988 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2989
2990 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002991 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002992 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002993 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002994
2995 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002996 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002997 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002998 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002999
3000 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3001 window1->consumeMotionMove();
3002 window1->assertNoEvents();
3003
3004 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003005 mDispatcher->notifyMotion(
3006 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003007 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003008 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003009
Prabir Pradhan678438e2023-04-13 19:32:51 +00003010 mDispatcher->notifyMotion(
3011 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003012 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003013 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003014}
3015
Garfield Tandf26e862020-07-01 20:18:19 -07003016TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003018 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003019 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003020 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003021 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003022 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003023 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003024
3025 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3026
3027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3028
3029 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003031 injectMotionEvent(mDispatcher,
3032 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3033 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003035 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003036 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003037
3038 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003040 injectMotionEvent(mDispatcher,
3041 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3042 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003044 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003045 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3046 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003047
3048 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003050 injectMotionEvent(mDispatcher,
3051 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3052 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003054 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003055 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3056 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
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_BUTTON_PRESS,
3061 AINPUT_SOURCE_MOUSE)
3062 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3063 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003064 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003065 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003066 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003067
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003069 injectMotionEvent(mDispatcher,
3070 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3071 AINPUT_SOURCE_MOUSE)
3072 .buttonState(0)
3073 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003074 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003075 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003076 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003077
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003079 injectMotionEvent(mDispatcher,
3080 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3081 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003082 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003083 .build()));
3084 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3085
3086 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003088 injectMotionEvent(mDispatcher,
3089 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3090 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003091 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003092 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003093 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003094
3095 // No more events
3096 windowLeft->assertNoEvents();
3097 windowRight->assertNoEvents();
3098}
3099
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100/**
3101 * Put two fingers down (and don't release them) and click the mouse button.
3102 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3103 * currently active gesture should be canceled, and the new one should proceed.
3104 */
3105TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3107 sp<FakeWindowHandle> window =
3108 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3109 window->setFrame(Rect(0, 0, 600, 800));
3110
3111 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3112
3113 const int32_t touchDeviceId = 4;
3114 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115
3116 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3118 .deviceId(touchDeviceId)
3119 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3120 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003121
Prabir Pradhan678438e2023-04-13 19:32:51 +00003122 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3123 .deviceId(touchDeviceId)
3124 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3125 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3126 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3128 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3129
3130 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003131 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3132 .deviceId(mouseDeviceId)
3133 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3137 WithPointerCount(2u)));
3138 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3139
Prabir Pradhan678438e2023-04-13 19:32:51 +00003140 mDispatcher->notifyMotion(
3141 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3142 .deviceId(mouseDeviceId)
3143 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3144 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3145 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3146 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003147 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3148
3149 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3150 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3152 .deviceId(touchDeviceId)
3153 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3154 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3155 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003156 window->assertNoEvents();
3157}
3158
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003159TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3161
3162 sp<FakeWindowHandle> spyWindow =
3163 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3164 spyWindow->setFrame(Rect(0, 0, 600, 800));
3165 spyWindow->setTrustedOverlay(true);
3166 spyWindow->setSpy(true);
3167 sp<FakeWindowHandle> window =
3168 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3169 window->setFrame(Rect(0, 0, 600, 800));
3170
3171 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3173
3174 // Send mouse cursor to the window
3175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3176 injectMotionEvent(mDispatcher,
3177 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3178 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003179 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003180 .x(100)
3181 .y(100))
3182 .build()));
3183
3184 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3185 WithSource(AINPUT_SOURCE_MOUSE)));
3186 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3187 WithSource(AINPUT_SOURCE_MOUSE)));
3188
3189 window->assertNoEvents();
3190 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003191}
3192
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003193TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3195
3196 sp<FakeWindowHandle> spyWindow =
3197 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3198 spyWindow->setFrame(Rect(0, 0, 600, 800));
3199 spyWindow->setTrustedOverlay(true);
3200 spyWindow->setSpy(true);
3201 sp<FakeWindowHandle> window =
3202 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3203 window->setFrame(Rect(0, 0, 600, 800));
3204
3205 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3206 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3207
3208 // Send mouse cursor to the window
3209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3210 injectMotionEvent(mDispatcher,
3211 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3212 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003213 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003214 .x(100)
3215 .y(100))
3216 .build()));
3217
3218 // Move mouse cursor
3219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3220 injectMotionEvent(mDispatcher,
3221 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3222 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003223 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003224 .x(110)
3225 .y(110))
3226 .build()));
3227
3228 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3229 WithSource(AINPUT_SOURCE_MOUSE)));
3230 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3231 WithSource(AINPUT_SOURCE_MOUSE)));
3232 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3233 WithSource(AINPUT_SOURCE_MOUSE)));
3234 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3235 WithSource(AINPUT_SOURCE_MOUSE)));
3236 // Touch down on the window
3237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3238 injectMotionEvent(mDispatcher,
3239 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3240 AINPUT_SOURCE_TOUCHSCREEN)
3241 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003242 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003243 .x(200)
3244 .y(200))
3245 .build()));
3246 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3247 WithSource(AINPUT_SOURCE_MOUSE)));
3248 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3249 WithSource(AINPUT_SOURCE_MOUSE)));
3250 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3251 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3252 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3253 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3254
3255 // pilfer the motion, retaining the gesture on the spy window.
3256 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3257 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3258 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3259
3260 // Touch UP on the window
3261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3262 injectMotionEvent(mDispatcher,
3263 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3264 AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003266 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003267 .x(200)
3268 .y(200))
3269 .build()));
3270 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3271 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3272
3273 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3274 // to send a new gesture. It should again go to both windows (spy and the window below), just
3275 // like the first gesture did, before pilfering. The window configuration has not changed.
3276
3277 // One more tap - DOWN
3278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3279 injectMotionEvent(mDispatcher,
3280 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3281 AINPUT_SOURCE_TOUCHSCREEN)
3282 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003283 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003284 .x(250)
3285 .y(250))
3286 .build()));
3287 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3288 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3289 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3290 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3291
3292 // Touch UP on the window
3293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3294 injectMotionEvent(mDispatcher,
3295 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3296 AINPUT_SOURCE_TOUCHSCREEN)
3297 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003298 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003299 .x(250)
3300 .y(250))
3301 .build()));
3302 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3303 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3304 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3305 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3306
3307 window->assertNoEvents();
3308 spyWindow->assertNoEvents();
3309}
3310
Garfield Tandf26e862020-07-01 20:18:19 -07003311// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3312// directly in this test.
3313TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003315 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003316 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003317 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003318
3319 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3320
3321 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3322
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003324 injectMotionEvent(mDispatcher,
3325 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3326 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003327 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003328 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003329 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003330 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003332 injectMotionEvent(mDispatcher,
3333 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3334 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003335 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003336 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003337 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3338 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
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_BUTTON_PRESS,
3343 AINPUT_SOURCE_MOUSE)
3344 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3345 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003346 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003347 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003348 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003349
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003351 injectMotionEvent(mDispatcher,
3352 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3353 AINPUT_SOURCE_MOUSE)
3354 .buttonState(0)
3355 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003356 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003357 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003358 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003361 injectMotionEvent(mDispatcher,
3362 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3363 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003364 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003365 .build()));
3366 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3367
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003368 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3369 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3370 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003371 injectMotionEvent(mDispatcher,
3372 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3373 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003374 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003375 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003376 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003377}
3378
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003379/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003380 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3381 * is generated.
3382 */
3383TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3384 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3385 sp<FakeWindowHandle> window =
3386 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3387 window->setFrame(Rect(0, 0, 1200, 800));
3388
3389 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3390
3391 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3392
3393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3394 injectMotionEvent(mDispatcher,
3395 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3396 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003397 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003398 .x(300)
3399 .y(400))
3400 .build()));
3401 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3402
3403 // Remove the window, but keep the channel.
3404 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3405 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3406}
3407
3408/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003409 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3410 */
3411TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3412 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3413 sp<FakeWindowHandle> window =
3414 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3415 window->setFrame(Rect(0, 0, 100, 100));
3416
3417 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3418
3419 const int32_t mouseDeviceId = 7;
3420 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003421
3422 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3424 .deviceId(mouseDeviceId)
3425 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3426 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003427 window->consumeMotionEvent(
3428 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3429
3430 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3432 .deviceId(touchDeviceId)
3433 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3434 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003435
3436 window->consumeMotionEvent(
3437 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3439}
3440
3441/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003442 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003443 * The tap causes a HOVER_EXIT event to be generated because the current event
3444 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003445 */
3446TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3448 sp<FakeWindowHandle> window =
3449 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3450 window->setFrame(Rect(0, 0, 100, 100));
3451
3452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3453
3454 // Inject a hover_move from mouse.
3455 NotifyMotionArgs motionArgs =
3456 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3457 ADISPLAY_ID_DEFAULT, {{50, 50}});
3458 motionArgs.xCursorPosition = 50;
3459 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003460 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003461 ASSERT_NO_FATAL_FAILURE(
3462 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3463 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003464
3465 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003466 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3467 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3468 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003469 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003470 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3471 WithSource(AINPUT_SOURCE_MOUSE))));
3472
3473 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003474 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3475 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3476
Prabir Pradhan678438e2023-04-13 19:32:51 +00003477 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3478 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003479 ASSERT_NO_FATAL_FAILURE(
3480 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3481 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3482}
3483
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003484TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3485 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3486 sp<FakeWindowHandle> windowDefaultDisplay =
3487 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3488 ADISPLAY_ID_DEFAULT);
3489 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3490 sp<FakeWindowHandle> windowSecondDisplay =
3491 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3492 SECOND_DISPLAY_ID);
3493 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3494
3495 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3496 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3497
3498 // Set cursor position in window in default display and check that hover enter and move
3499 // events are generated.
3500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3501 injectMotionEvent(mDispatcher,
3502 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3503 AINPUT_SOURCE_MOUSE)
3504 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003505 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003506 .x(300)
3507 .y(600))
3508 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003509 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003510
3511 // Remove all windows in secondary display and check that no event happens on window in
3512 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003513 mDispatcher->setInputWindows(
3514 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003515 windowDefaultDisplay->assertNoEvents();
3516
3517 // Move cursor position in window in default display and check that only hover move
3518 // event is generated and not hover enter event.
3519 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3520 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3522 injectMotionEvent(mDispatcher,
3523 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3524 AINPUT_SOURCE_MOUSE)
3525 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003526 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003527 .x(400)
3528 .y(700))
3529 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003530 windowDefaultDisplay->consumeMotionEvent(
3531 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3532 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003533 windowDefaultDisplay->assertNoEvents();
3534}
3535
Garfield Tan00f511d2019-06-12 16:55:40 -07003536TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003537 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003538
3539 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003540 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003541 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003542 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003543 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003544 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003545
3546 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3547
Arthur Hung72d8dc32020-03-28 00:48:39 +00003548 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003549
3550 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3551 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003553 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003554 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003555 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003556 windowRight->assertNoEvents();
3557}
3558
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003559TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003560 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003561 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3562 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003563 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003564
Arthur Hung72d8dc32020-03-28 00:48:39 +00003565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003566 setFocusedWindow(window);
3567
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003568 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003569
Prabir Pradhan678438e2023-04-13 19:32:51 +00003570 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003571
3572 // Window should receive key down event.
3573 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3574
3575 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3576 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003577 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003578 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003579 AKEY_EVENT_FLAG_CANCELED);
3580}
3581
3582TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3585 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003586
Arthur Hung72d8dc32020-03-28 00:48:39 +00003587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003588
Prabir Pradhan678438e2023-04-13 19:32:51 +00003589 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3590 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003591
3592 // Window should receive motion down event.
3593 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3594
3595 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3596 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003597 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003598 window->consumeMotionEvent(
3599 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003600}
3601
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003602TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3604 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3605 "Fake Window", ADISPLAY_ID_DEFAULT);
3606
3607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3608
3609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3610 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3611 .build());
3612
3613 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3614
3615 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3616 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3617 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3618
3619 // After the device has been reset, a new hovering stream can be sent to the window
3620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3621 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3622 .build());
3623 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3624}
3625
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003626TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3627 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003628 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3629 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003630 window->setFocusable(true);
3631
3632 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3633 setFocusedWindow(window);
3634
3635 window->consumeFocusEvent(true);
3636
Prabir Pradhan678438e2023-04-13 19:32:51 +00003637 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003638 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3639 const nsecs_t injectTime = keyArgs.eventTime;
3640 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003641 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003642 // The dispatching time should be always greater than or equal to intercept key timeout.
3643 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3644 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3645 std::chrono::nanoseconds(interceptKeyTimeout).count());
3646}
3647
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003648/**
3649 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3650 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003651TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3652 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003653 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3654 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003655 window->setFocusable(true);
3656
3657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3658 setFocusedWindow(window);
3659
3660 window->consumeFocusEvent(true);
3661
Prabir Pradhan678438e2023-04-13 19:32:51 +00003662 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003663 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003664
3665 // Set a value that's significantly larger than the default consumption timeout. If the
3666 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3667 mFakePolicy->setInterceptKeyTimeout(600ms);
3668 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3669 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003670 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3671}
3672
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003673/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003674 * Two windows. First is a regular window. Second does not overlap with the first, and has
3675 * WATCH_OUTSIDE_TOUCH.
3676 * Both windows are owned by the same UID.
3677 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3678 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3679 */
3680TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3681 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3682 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3683 "First Window", ADISPLAY_ID_DEFAULT);
3684 window->setFrame(Rect{0, 0, 100, 100});
3685
3686 sp<FakeWindowHandle> outsideWindow =
3687 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3688 ADISPLAY_ID_DEFAULT);
3689 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3690 outsideWindow->setWatchOutsideTouch(true);
3691 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3692 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3693
3694 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003695 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3696 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3697 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003698 window->consumeMotionDown();
3699 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3700 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3701 outsideWindow->consumeMotionEvent(
3702 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3703}
3704
3705/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003706 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3707 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3708 * ACTION_OUTSIDE event is sent per gesture.
3709 */
3710TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3711 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003713 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3714 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003715 window->setWatchOutsideTouch(true);
3716 window->setFrame(Rect{0, 0, 100, 100});
3717 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003718 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3719 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003720 secondWindow->setFrame(Rect{100, 100, 200, 200});
3721 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003722 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3723 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003724 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3726
3727 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003728 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3729 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3730 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003731 window->assertNoEvents();
3732 secondWindow->assertNoEvents();
3733
3734 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3735 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003736 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3737 ADISPLAY_ID_DEFAULT,
3738 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003739 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3740 window->consumeMotionEvent(
3741 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003742 secondWindow->consumeMotionDown();
3743 thirdWindow->assertNoEvents();
3744
3745 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3746 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003747 mDispatcher->notifyMotion(
3748 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3749 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003750 window->assertNoEvents();
3751 secondWindow->consumeMotionMove();
3752 thirdWindow->consumeMotionDown();
3753}
3754
Prabir Pradhan814fe082022-07-22 20:22:18 +00003755TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3756 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003757 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3758 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003759 window->setFocusable(true);
3760
Patrick Williamsd828f302023-04-28 17:52:08 -05003761 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003762 setFocusedWindow(window);
3763
3764 window->consumeFocusEvent(true);
3765
Prabir Pradhan678438e2023-04-13 19:32:51 +00003766 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3767 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3768 mDispatcher->notifyKey(keyDown);
3769 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003770
3771 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3772 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3773
3774 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003775 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003776
3777 window->consumeFocusEvent(false);
3778
Prabir Pradhan678438e2023-04-13 19:32:51 +00003779 mDispatcher->notifyKey(keyDown);
3780 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003781 window->assertNoEvents();
3782}
3783
Arthur Hung96483742022-11-15 03:30:48 +00003784TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3787 "Fake Window", ADISPLAY_ID_DEFAULT);
3788 // Ensure window is non-split and have some transform.
3789 window->setPreventSplitting(true);
3790 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003792
3793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3794 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3795 {50, 50}))
3796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3797 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3798
3799 const MotionEvent secondFingerDownEvent =
3800 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3801 .displayId(ADISPLAY_ID_DEFAULT)
3802 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003803 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3804 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003805 .build();
3806 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3807 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3808 InputEventInjectionSync::WAIT_FOR_RESULT))
3809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3810
3811 const MotionEvent* event = window->consumeMotion();
3812 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3813 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3814 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3815 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3816 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3817}
3818
Harry Cuttsb166c002023-05-09 13:06:05 +00003819TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3821 sp<FakeWindowHandle> window =
3822 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3823 window->setFrame(Rect(0, 0, 400, 400));
3824 sp<FakeWindowHandle> trustedOverlay =
3825 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3826 ADISPLAY_ID_DEFAULT);
3827 trustedOverlay->setSpy(true);
3828 trustedOverlay->setTrustedOverlay(true);
3829
3830 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3831
3832 // Start a three-finger touchpad swipe
3833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3834 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3835 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3836 .build());
3837 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3838 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3839 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3840 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3841 .build());
3842 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3843 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3844 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3845 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3846 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3847 .build());
3848
3849 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3850 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3851 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3852
3853 // Move the swipe a bit
3854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3855 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3856 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3857 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3858 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3859 .build());
3860
3861 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3862
3863 // End the swipe
3864 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3865 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3866 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3867 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3868 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3869 .build());
3870 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3872 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3873 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3874 .build());
3875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3876 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3877 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3878 .build());
3879
3880 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3881 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3882 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3883
3884 window->assertNoEvents();
3885}
3886
3887TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3888 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3889 sp<FakeWindowHandle> window =
3890 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3891 window->setFrame(Rect(0, 0, 400, 400));
3892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3893
3894 // Start a three-finger touchpad swipe
3895 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3897 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3898 .build());
3899 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3900 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3901 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3902 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3903 .build());
3904 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3905 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3906 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3907 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3909 .build());
3910
3911 // Move the swipe a bit
3912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3913 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3914 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3915 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3916 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3917 .build());
3918
3919 // End the swipe
3920 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3921 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3922 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3923 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3924 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3925 .build());
3926 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3927 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3928 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3929 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3930 .build());
3931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3932 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3933 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3934 .build());
3935
3936 window->assertNoEvents();
3937}
3938
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003939/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003940 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3941 * the first pointer.
3942 * Ensure that the second pointer is not sent to the window.
3943 *
3944 * The subsequent gesture should be correctly delivered to the window.
3945 */
3946TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3948 sp<FakeWindowHandle> window =
3949 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3950 window->setFrame(Rect(0, 0, 400, 400));
3951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3952
3953 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3955 .downTime(baseTime + 10)
3956 .eventTime(baseTime + 10)
3957 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3958 .build());
3959
3960 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3961
3962 // We need a new window object for the same window, because dispatcher will store objects by
3963 // reference. That means that the testing code and the dispatcher will refer to the same shared
3964 // object. Calling window->setTransform here would affect dispatcher's comparison
3965 // of the old window to the new window, since both the old window and the new window would be
3966 // updated to the same value.
3967 sp<FakeWindowHandle> windowDup = window->duplicate();
3968
3969 // Change the transform so that the orientation is now different from original.
3970 windowDup->setWindowTransform(0, -1, 1, 0);
3971
3972 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3973
3974 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3975
3976 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3977 .downTime(baseTime + 10)
3978 .eventTime(baseTime + 30)
3979 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3980 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3981 .build());
3982
3983 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
3984 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3985 .downTime(baseTime + 10)
3986 .eventTime(baseTime + 40)
3987 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3988 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3989 .build());
3990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3991 .downTime(baseTime + 10)
3992 .eventTime(baseTime + 50)
3993 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3994 .build());
3995
3996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3997 .downTime(baseTime + 60)
3998 .eventTime(baseTime + 60)
3999 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4000 .build());
4001
4002 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4003}
4004
4005/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004006 * Ensure the correct coordinate spaces are used by InputDispatcher.
4007 *
4008 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4009 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4010 * space.
4011 */
4012class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4013public:
4014 void SetUp() override {
4015 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004016 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004017 }
4018
4019 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4020 gui::DisplayInfo info;
4021 info.displayId = displayId;
4022 info.transform = transform;
4023 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004024 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004025 }
4026
4027 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4028 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004029 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004030 }
4031
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004032 void removeAllWindowsAndDisplays() {
4033 mDisplayInfos.clear();
4034 mWindowInfos.clear();
4035 }
4036
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004037 // Set up a test scenario where the display has a scaled projection and there are two windows
4038 // on the display.
4039 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4040 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4041 // respectively.
4042 ui::Transform displayTransform;
4043 displayTransform.set(2, 0, 0, 4);
4044 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4045
4046 std::shared_ptr<FakeApplicationHandle> application =
4047 std::make_shared<FakeApplicationHandle>();
4048
4049 // Add two windows to the display. Their frames are represented in the display space.
4050 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004051 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4052 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004053 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4054 addWindow(firstWindow);
4055
4056 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004057 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4058 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004059 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4060 addWindow(secondWindow);
4061 return {std::move(firstWindow), std::move(secondWindow)};
4062 }
4063
4064private:
4065 std::vector<gui::DisplayInfo> mDisplayInfos;
4066 std::vector<gui::WindowInfo> mWindowInfos;
4067};
4068
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004069TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004070 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4071 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004072 // selected so that if the hit test was performed with the point and the bounds being in
4073 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004074 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4075 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4076 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004077
4078 firstWindow->consumeMotionDown();
4079 secondWindow->assertNoEvents();
4080}
4081
4082// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4083// the event should be treated as being in the logical display space.
4084TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4085 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4086 // Send down to the first window. The point is represented in the logical display space. The
4087 // point is selected so that if the hit test was done in logical display space, then it would
4088 // end up in the incorrect window.
4089 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4090 PointF{75 * 2, 55 * 4});
4091
4092 firstWindow->consumeMotionDown();
4093 secondWindow->assertNoEvents();
4094}
4095
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004096// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4097// event should be treated as being in the logical display space.
4098TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4099 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4100
4101 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4102 ui::Transform injectedEventTransform;
4103 injectedEventTransform.set(matrix);
4104 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4105 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4106
4107 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4108 .displayId(ADISPLAY_ID_DEFAULT)
4109 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004110 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004111 .x(untransformedPoint.x)
4112 .y(untransformedPoint.y))
4113 .build();
4114 event.transform(matrix);
4115
4116 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4117 InputEventInjectionSync::WAIT_FOR_RESULT);
4118
4119 firstWindow->consumeMotionDown();
4120 secondWindow->assertNoEvents();
4121}
4122
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004123TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4124 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4125
4126 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004127 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4128 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4129 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004130
4131 firstWindow->assertNoEvents();
4132 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004133 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004134 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4135
4136 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4137 EXPECT_EQ(300, event->getRawX(0));
4138 EXPECT_EQ(880, event->getRawY(0));
4139
4140 // Ensure that the x and y values are in the window's coordinate space.
4141 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4142 // the logical display space. This will be the origin of the window space.
4143 EXPECT_EQ(100, event->getX(0));
4144 EXPECT_EQ(80, event->getY(0));
4145}
4146
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004147/** Ensure consistent behavior of InputDispatcher in all orientations. */
4148class InputDispatcherDisplayOrientationFixture
4149 : public InputDispatcherDisplayProjectionTest,
4150 public ::testing::WithParamInterface<ui::Rotation> {};
4151
4152// This test verifies the touchable region of a window for all rotations of the display by tapping
4153// in different locations on the display, specifically points close to the four corners of a
4154// window.
4155TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4156 constexpr static int32_t displayWidth = 400;
4157 constexpr static int32_t displayHeight = 800;
4158
4159 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4160
4161 const auto rotation = GetParam();
4162
4163 // Set up the display with the specified rotation.
4164 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4165 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4166 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4167 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4168 logicalDisplayWidth, logicalDisplayHeight);
4169 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4170
4171 // Create a window with its bounds determined in the logical display.
4172 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4173 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4174 sp<FakeWindowHandle> window =
4175 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4176 window->setFrame(frameInDisplay, displayTransform);
4177 addWindow(window);
4178
4179 // The following points in logical display space should be inside the window.
4180 static const std::array<vec2, 4> insidePoints{
4181 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4182 for (const auto pointInsideWindow : insidePoints) {
4183 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4184 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4186 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4187 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004188 window->consumeMotionDown();
4189
Prabir Pradhan678438e2023-04-13 19:32:51 +00004190 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4191 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4192 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004193 window->consumeMotionUp();
4194 }
4195
4196 // The following points in logical display space should be outside the window.
4197 static const std::array<vec2, 5> outsidePoints{
4198 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4199 for (const auto pointOutsideWindow : outsidePoints) {
4200 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4201 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004202 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4203 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4204 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004205
Prabir Pradhan678438e2023-04-13 19:32:51 +00004206 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4207 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4208 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004209 }
4210 window->assertNoEvents();
4211}
4212
4213// Run the precision tests for all rotations.
4214INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4215 InputDispatcherDisplayOrientationFixture,
4216 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4217 ui::ROTATION_270),
4218 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4219 return ftl::enum_string(testParamInfo.param);
4220 });
4221
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004222using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4223 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004224
4225class TransferTouchFixture : public InputDispatcherTest,
4226 public ::testing::WithParamInterface<TransferFunction> {};
4227
4228TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004230
4231 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004232 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004233 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4234 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004235 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004236 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004237 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4238 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004239 sp<FakeWindowHandle> wallpaper =
4240 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4241 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004242 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244
4245 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004246 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4247 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004248
Svet Ganov5d3bc372020-01-26 23:11:07 -08004249 // Only the first window should get the down event
4250 firstWindow->consumeMotionDown();
4251 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004252 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004253
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004254 // Transfer touch to the second window
4255 TransferFunction f = GetParam();
4256 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4257 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004258 // The first window gets cancel and the second gets down
4259 firstWindow->consumeMotionCancel();
4260 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004261 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004262
4263 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004264 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4265 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004266 // The first window gets no events and the second gets up
4267 firstWindow->assertNoEvents();
4268 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004269 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004270}
4271
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004272/**
4273 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4274 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4275 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4276 * natural to the user.
4277 * In this test, we are sending a pointer to both spy window and first window. We then try to
4278 * transfer touch to the second window. The dispatcher should identify the first window as the
4279 * one that should lose the gesture, and therefore the action should be to move the gesture from
4280 * the first window to the second.
4281 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4282 * the other API, as well.
4283 */
4284TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4286
4287 // Create a couple of windows + a spy window
4288 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004289 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004290 spyWindow->setTrustedOverlay(true);
4291 spyWindow->setSpy(true);
4292 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004293 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004294 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004295 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004296
4297 // Add the windows to the dispatcher
4298 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4299
4300 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004301 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4302 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004303 // Only the first window and spy should get the down event
4304 spyWindow->consumeMotionDown();
4305 firstWindow->consumeMotionDown();
4306
4307 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4308 // if f === 'transferTouch'.
4309 TransferFunction f = GetParam();
4310 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4311 ASSERT_TRUE(success);
4312 // The first window gets cancel and the second gets down
4313 firstWindow->consumeMotionCancel();
4314 secondWindow->consumeMotionDown();
4315
4316 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004317 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4318 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004319 // The first window gets no events and the second+spy get up
4320 firstWindow->assertNoEvents();
4321 spyWindow->consumeMotionUp();
4322 secondWindow->consumeMotionUp();
4323}
4324
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004325TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004327
4328 PointF touchPoint = {10, 10};
4329
4330 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004331 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004332 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4333 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004334 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004335 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004336 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4337 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004338 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004339
4340 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004342
4343 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004344 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4345 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4346 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004347 // Only the first window should get the down event
4348 firstWindow->consumeMotionDown();
4349 secondWindow->assertNoEvents();
4350
4351 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004352 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4353 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004354 // Only the first window should get the pointer down event
4355 firstWindow->consumeMotionPointerDown(1);
4356 secondWindow->assertNoEvents();
4357
4358 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004359 TransferFunction f = GetParam();
4360 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4361 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004362 // The first window gets cancel and the second gets down and pointer down
4363 firstWindow->consumeMotionCancel();
4364 secondWindow->consumeMotionDown();
4365 secondWindow->consumeMotionPointerDown(1);
4366
4367 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004368 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4369 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004370 // The first window gets nothing and the second gets pointer up
4371 firstWindow->assertNoEvents();
4372 secondWindow->consumeMotionPointerUp(1);
4373
4374 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004375 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4376 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004377 // The first window gets nothing and the second gets up
4378 firstWindow->assertNoEvents();
4379 secondWindow->consumeMotionUp();
4380}
4381
Arthur Hungc539dbb2022-12-08 07:45:36 +00004382TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4384
4385 // Create a couple of windows
4386 sp<FakeWindowHandle> firstWindow =
4387 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4388 ADISPLAY_ID_DEFAULT);
4389 firstWindow->setDupTouchToWallpaper(true);
4390 sp<FakeWindowHandle> secondWindow =
4391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4392 ADISPLAY_ID_DEFAULT);
4393 secondWindow->setDupTouchToWallpaper(true);
4394
4395 sp<FakeWindowHandle> wallpaper1 =
4396 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4397 wallpaper1->setIsWallpaper(true);
4398
4399 sp<FakeWindowHandle> wallpaper2 =
4400 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4401 wallpaper2->setIsWallpaper(true);
4402 // Add the windows to the dispatcher
4403 mDispatcher->setInputWindows(
4404 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4405
4406 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4408 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004409
4410 // Only the first window should get the down event
4411 firstWindow->consumeMotionDown();
4412 secondWindow->assertNoEvents();
4413 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4414 wallpaper2->assertNoEvents();
4415
4416 // Transfer touch focus to the second window
4417 TransferFunction f = GetParam();
4418 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4419 ASSERT_TRUE(success);
4420
4421 // The first window gets cancel and the second gets down
4422 firstWindow->consumeMotionCancel();
4423 secondWindow->consumeMotionDown();
4424 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4425 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4426
4427 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004428 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4429 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004430 // The first window gets no events and the second gets up
4431 firstWindow->assertNoEvents();
4432 secondWindow->consumeMotionUp();
4433 wallpaper1->assertNoEvents();
4434 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4435}
4436
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004437// For the cases of single pointer touch and two pointers non-split touch, the api's
4438// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4439// for the case where there are multiple pointers split across several windows.
4440INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4441 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004442 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4443 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004444 return dispatcher->transferTouch(destChannelToken,
4445 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004446 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004447 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4448 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004449 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004450 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004451 }));
4452
Svet Ganov5d3bc372020-01-26 23:11:07 -08004453TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004455
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004456 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004457 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4458 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004460
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004461 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004462 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4463 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004464 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004465
4466 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004467 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004468
4469 PointF pointInFirst = {300, 200};
4470 PointF pointInSecond = {300, 600};
4471
4472 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004473 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4474 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4475 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004476 // Only the first window should get the down event
4477 firstWindow->consumeMotionDown();
4478 secondWindow->assertNoEvents();
4479
4480 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004481 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4482 ADISPLAY_ID_DEFAULT,
4483 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004484 // The first window gets a move and the second a down
4485 firstWindow->consumeMotionMove();
4486 secondWindow->consumeMotionDown();
4487
4488 // Transfer touch focus to the second window
4489 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4490 // The first window gets cancel and the new gets pointer down (it already saw down)
4491 firstWindow->consumeMotionCancel();
4492 secondWindow->consumeMotionPointerDown(1);
4493
4494 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004495 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4496 ADISPLAY_ID_DEFAULT,
4497 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004498 // The first window gets nothing and the second gets pointer up
4499 firstWindow->assertNoEvents();
4500 secondWindow->consumeMotionPointerUp(1);
4501
4502 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004503 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4504 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004505 // The first window gets nothing and the second gets up
4506 firstWindow->assertNoEvents();
4507 secondWindow->consumeMotionUp();
4508}
4509
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004510// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4511// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4512// touch is not supported, so the touch should continue on those windows and the transferred-to
4513// window should get nothing.
4514TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4516
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004517 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004518 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4519 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004520 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004521
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004522 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004523 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4524 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004525 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004526
4527 // Add the windows to the dispatcher
4528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4529
4530 PointF pointInFirst = {300, 200};
4531 PointF pointInSecond = {300, 600};
4532
4533 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004534 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4535 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4536 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004537 // Only the first window should get the down event
4538 firstWindow->consumeMotionDown();
4539 secondWindow->assertNoEvents();
4540
4541 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004542 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4543 ADISPLAY_ID_DEFAULT,
4544 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004545 // The first window gets a move and the second a down
4546 firstWindow->consumeMotionMove();
4547 secondWindow->consumeMotionDown();
4548
4549 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004550 const bool transferred =
4551 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004552 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4553 ASSERT_FALSE(transferred);
4554 firstWindow->assertNoEvents();
4555 secondWindow->assertNoEvents();
4556
4557 // The rest of the dispatch should proceed as normal
4558 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004559 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4560 ADISPLAY_ID_DEFAULT,
4561 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004562 // The first window gets MOVE and the second gets pointer up
4563 firstWindow->consumeMotionMove();
4564 secondWindow->consumeMotionUp();
4565
4566 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004567 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4568 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004569 // The first window gets nothing and the second gets up
4570 firstWindow->consumeMotionUp();
4571 secondWindow->assertNoEvents();
4572}
4573
Arthur Hungabbb9d82021-09-01 14:52:30 +00004574// This case will create two windows and one mirrored window on the default display and mirror
4575// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4576// the windows info of second display before default display.
4577TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4579 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004580 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004581 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004583 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004584 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004585
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004586 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004587 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004588
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004589 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004590 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004591
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004592 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004593 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004594
4595 // Update window info, let it find window handle of second display first.
4596 mDispatcher->setInputWindows(
4597 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4598 {ADISPLAY_ID_DEFAULT,
4599 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4600
4601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4602 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4603 {50, 50}))
4604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4605
4606 // Window should receive motion event.
4607 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4608
4609 // Transfer touch focus
4610 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4611 secondWindowInPrimary->getToken()));
4612 // The first window gets cancel.
4613 firstWindowInPrimary->consumeMotionCancel();
4614 secondWindowInPrimary->consumeMotionDown();
4615
4616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4617 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4618 ADISPLAY_ID_DEFAULT, {150, 50}))
4619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4620 firstWindowInPrimary->assertNoEvents();
4621 secondWindowInPrimary->consumeMotionMove();
4622
4623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4624 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4625 {150, 50}))
4626 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4627 firstWindowInPrimary->assertNoEvents();
4628 secondWindowInPrimary->consumeMotionUp();
4629}
4630
4631// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4632// 'transferTouch' api.
4633TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4635 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004636 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004637 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004638 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004639 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004640 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004642 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004643 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004644
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004645 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004646 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004647
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004648 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004649 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004650
4651 // Update window info, let it find window handle of second display first.
4652 mDispatcher->setInputWindows(
4653 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4654 {ADISPLAY_ID_DEFAULT,
4655 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4656
4657 // Touch on second display.
4658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4659 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4661
4662 // Window should receive motion event.
4663 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4664
4665 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004666 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004667
4668 // The first window gets cancel.
4669 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4670 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4671
4672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4673 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4674 SECOND_DISPLAY_ID, {150, 50}))
4675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4676 firstWindowInPrimary->assertNoEvents();
4677 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4678
4679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4680 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4682 firstWindowInPrimary->assertNoEvents();
4683 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4684}
4685
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004686TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004688 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4689 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004690
Vishnu Nair47074b82020-08-14 11:54:47 -07004691 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004692 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004693 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004694
4695 window->consumeFocusEvent(true);
4696
Prabir Pradhan678438e2023-04-13 19:32:51 +00004697 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004698
4699 // Window should receive key down event.
4700 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004701
4702 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004703 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004704 mFakePolicy->assertUserActivityPoked();
4705}
4706
4707TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4709 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4710 "Fake Window", ADISPLAY_ID_DEFAULT);
4711
4712 window->setDisableUserActivity(true);
4713 window->setFocusable(true);
4714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4715 setFocusedWindow(window);
4716
4717 window->consumeFocusEvent(true);
4718
4719 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4720
4721 // Window should receive key down event.
4722 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4723
4724 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004725 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004726 mFakePolicy->assertUserActivityNotPoked();
4727}
4728
4729TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4731 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4732 "Fake Window", ADISPLAY_ID_DEFAULT);
4733
4734 window->setFocusable(true);
4735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4736 setFocusedWindow(window);
4737
4738 window->consumeFocusEvent(true);
4739
4740 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4741 mDispatcher->waitForIdle();
4742
4743 // System key is not passed down
4744 window->assertNoEvents();
4745
4746 // Should have poked user activity
4747 mFakePolicy->assertUserActivityPoked();
4748}
4749
4750TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4752 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4753 "Fake Window", ADISPLAY_ID_DEFAULT);
4754
4755 window->setFocusable(true);
4756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4757 setFocusedWindow(window);
4758
4759 window->consumeFocusEvent(true);
4760
4761 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4762 mDispatcher->waitForIdle();
4763
4764 // System key is not passed down
4765 window->assertNoEvents();
4766
4767 // Should have poked user activity
4768 mFakePolicy->assertUserActivityPoked();
4769}
4770
4771TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4773 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4774 "Fake Window", ADISPLAY_ID_DEFAULT);
4775
4776 window->setDisableUserActivity(true);
4777 window->setFocusable(true);
4778 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4779 setFocusedWindow(window);
4780
4781 window->consumeFocusEvent(true);
4782
4783 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4784 mDispatcher->waitForIdle();
4785
4786 // System key is not passed down
4787 window->assertNoEvents();
4788
4789 // Should have poked user activity
4790 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004791}
4792
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004793TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4794 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4795 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4796 "Fake Window", ADISPLAY_ID_DEFAULT);
4797
4798 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4799
4800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4801 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4802 ADISPLAY_ID_DEFAULT, {100, 100}))
4803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4804
4805 window->consumeMotionEvent(
4806 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4807
4808 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004809 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004810 mFakePolicy->assertUserActivityPoked();
4811}
4812
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004813TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004814 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004815 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4816 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004817
Arthur Hung72d8dc32020-03-28 00:48:39 +00004818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004819
Prabir Pradhan678438e2023-04-13 19:32:51 +00004820 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004821 mDispatcher->waitForIdle();
4822
4823 window->assertNoEvents();
4824}
4825
4826// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4827TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4830 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004831
Arthur Hung72d8dc32020-03-28 00:48:39 +00004832 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004833
4834 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004835 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004836 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004837 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4838 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004839
4840 // Window should receive only the motion event
4841 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4842 window->assertNoEvents(); // Key event or focus event will not be received
4843}
4844
arthurhungea3f4fc2020-12-21 23:18:53 +08004845TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4846 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4847
arthurhungea3f4fc2020-12-21 23:18:53 +08004848 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004849 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4850 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004851 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004852
arthurhungea3f4fc2020-12-21 23:18:53 +08004853 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004854 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4855 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004856 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004857
4858 // Add the windows to the dispatcher
4859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4860
4861 PointF pointInFirst = {300, 200};
4862 PointF pointInSecond = {300, 600};
4863
4864 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004865 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4866 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4867 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004868 // Only the first window should get the down event
4869 firstWindow->consumeMotionDown();
4870 secondWindow->assertNoEvents();
4871
4872 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004873 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4874 ADISPLAY_ID_DEFAULT,
4875 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004876 // The first window gets a move and the second a down
4877 firstWindow->consumeMotionMove();
4878 secondWindow->consumeMotionDown();
4879
4880 // Send pointer cancel to the second window
4881 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004882 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004883 {pointInFirst, pointInSecond});
4884 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004885 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004886 // The first window gets move and the second gets cancel.
4887 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4888 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4889
4890 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004891 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4892 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004893 // The first window gets up and the second gets nothing.
4894 firstWindow->consumeMotionUp();
4895 secondWindow->assertNoEvents();
4896}
4897
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004898TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4900
4901 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004902 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004903 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4904 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4905 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4906 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4907
Harry Cutts33476232023-01-30 19:57:29 +00004908 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004909 window->assertNoEvents();
4910 mDispatcher->waitForIdle();
4911}
4912
chaviwd1c23182019-12-20 18:44:56 -08004913class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004914public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004915 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004916 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004917 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004918 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004919 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004920 }
4921
chaviwd1c23182019-12-20 18:44:56 -08004922 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4923
4924 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004925 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4926 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004927 }
4928
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004929 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4930
4931 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4932
chaviwd1c23182019-12-20 18:44:56 -08004933 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004934 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004935 expectedDisplayId, expectedFlags);
4936 }
4937
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004938 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004939 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004940 expectedDisplayId, expectedFlags);
4941 }
4942
chaviwd1c23182019-12-20 18:44:56 -08004943 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004944 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004945 expectedDisplayId, expectedFlags);
4946 }
4947
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004948 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004949 mInputReceiver->consumeMotionEvent(
4950 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4951 WithDisplayId(expectedDisplayId),
4952 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004953 }
4954
Arthur Hungfbfa5722021-11-16 02:45:54 +00004955 void consumeMotionPointerDown(int32_t pointerIdx) {
4956 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4957 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004958 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004959 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004960 }
4961
Evan Rosky84f07f02021-04-16 10:42:42 -07004962 MotionEvent* consumeMotion() {
4963 InputEvent* event = mInputReceiver->consume();
4964 if (!event) {
4965 ADD_FAILURE() << "No event was produced";
4966 return nullptr;
4967 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004968 if (event->getType() != InputEventType::MOTION) {
4969 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004970 return nullptr;
4971 }
4972 return static_cast<MotionEvent*>(event);
4973 }
4974
chaviwd1c23182019-12-20 18:44:56 -08004975 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4976
4977private:
4978 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004979};
4980
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004981using InputDispatcherMonitorTest = InputDispatcherTest;
4982
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004983/**
4984 * Two entities that receive touch: A window, and a global monitor.
4985 * The touch goes to the window, and then the window disappears.
4986 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4987 * for the monitor, as well.
4988 * 1. foregroundWindow
4989 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4990 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004991TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004992 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4993 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004994 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004995
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004996 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004997
4998 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5000 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5001 {100, 200}))
5002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5003
5004 // Both the foreground window and the global monitor should receive the touch down
5005 window->consumeMotionDown();
5006 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5007
5008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5009 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5010 ADISPLAY_ID_DEFAULT, {110, 200}))
5011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5012
5013 window->consumeMotionMove();
5014 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5015
5016 // Now the foreground window goes away
5017 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5018 window->consumeMotionCancel();
5019 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5020
5021 // If more events come in, there will be no more foreground window to send them to. This will
5022 // cause a cancel for the monitor, as well.
5023 ASSERT_EQ(InputEventInjectionResult::FAILED,
5024 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5025 ADISPLAY_ID_DEFAULT, {120, 200}))
5026 << "Injection should fail because the window was removed";
5027 window->assertNoEvents();
5028 // Global monitor now gets the cancel
5029 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5030}
5031
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005032TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005033 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005034 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5035 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005036 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005037
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005038 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005039
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005040 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005041 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005043 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005044 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005045}
5046
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005047TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5048 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005049
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 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005053 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005054
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005056 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005058 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005059 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005060
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005061 // Pilfer pointers from the monitor.
5062 // This should not do anything and the window should continue to receive events.
5063 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005064
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005066 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5067 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005069
5070 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5071 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005072}
5073
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005074TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5077 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005078 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5079 window->setWindowOffset(20, 40);
5080 window->setWindowTransform(0, 1, -1, 0);
5081
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005082 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005083
5084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5085 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5086 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5087 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5088 MotionEvent* event = monitor.consumeMotion();
5089 // Even though window has transform, gesture monitor must not.
5090 ASSERT_EQ(ui::Transform(), event->getTransform());
5091}
5092
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005093TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005095 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005096
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005097 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005098 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005099 << "Injection should fail if there is a monitor, but no touchable window";
5100 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005101}
5102
chaviw81e2bb92019-12-18 15:03:51 -08005103TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005104 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005105 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5106 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005107
Arthur Hung72d8dc32020-03-28 00:48:39 +00005108 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005109
5110 NotifyMotionArgs motionArgs =
5111 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5112 ADISPLAY_ID_DEFAULT);
5113
Prabir Pradhan678438e2023-04-13 19:32:51 +00005114 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005115 // Window should receive motion down event.
5116 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5117
5118 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005119 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005120 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5121 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5122 motionArgs.pointerCoords[0].getX() - 10);
5123
Prabir Pradhan678438e2023-04-13 19:32:51 +00005124 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005125 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005126 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005127}
5128
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005129/**
5130 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5131 * the device default right away. In the test scenario, we check both the default value,
5132 * and the action of enabling / disabling.
5133 */
5134TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
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);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005138 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005139
5140 // Set focused application.
5141 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005142 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005143
5144 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005146 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005147 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005148
5149 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005150 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005152 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005153
5154 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005155 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005156 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005157 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005158 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005160 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005161 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005162
5163 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005164 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005165 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005166 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005167
5168 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005169 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005170 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005171 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005172 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005173 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005174 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005175 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005176
5177 window->assertNoEvents();
5178}
5179
Gang Wange9087892020-01-07 12:17:14 -05005180TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005182 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5183 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005184
5185 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005186 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005187
Arthur Hung72d8dc32020-03-28 00:48:39 +00005188 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005189 setFocusedWindow(window);
5190
Harry Cutts33476232023-01-30 19:57:29 +00005191 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005192
Prabir Pradhan678438e2023-04-13 19:32:51 +00005193 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5194 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005195
5196 InputEvent* event = window->consume();
5197 ASSERT_NE(event, nullptr);
5198
5199 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5200 ASSERT_NE(verified, nullptr);
5201 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5202
5203 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5204 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5205 ASSERT_EQ(keyArgs.source, verified->source);
5206 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5207
5208 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5209
5210 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005211 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005212 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005213 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5214 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5215 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5216 ASSERT_EQ(0, verifiedKey.repeatCount);
5217}
5218
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005219TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005221 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5222 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005223
5224 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5225
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005226 ui::Transform transform;
5227 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5228
5229 gui::DisplayInfo displayInfo;
5230 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5231 displayInfo.transform = transform;
5232
Patrick Williamsd828f302023-04-28 17:52:08 -05005233 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005234
Prabir Pradhan678438e2023-04-13 19:32:51 +00005235 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005236 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5237 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005238 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005239
5240 InputEvent* event = window->consume();
5241 ASSERT_NE(event, nullptr);
5242
5243 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5244 ASSERT_NE(verified, nullptr);
5245 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5246
5247 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5248 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5249 EXPECT_EQ(motionArgs.source, verified->source);
5250 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5251
5252 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5253
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005254 const vec2 rawXY =
5255 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5256 motionArgs.pointerCoords[0].getXYValue());
5257 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5258 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005259 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005260 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005261 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005262 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5263 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5264}
5265
chaviw09c8d2d2020-08-24 15:48:26 -07005266/**
5267 * Ensure that separate calls to sign the same data are generating the same key.
5268 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5269 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5270 * tests.
5271 */
5272TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5273 KeyEvent event = getTestKeyEvent();
5274 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5275
5276 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5277 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5278 ASSERT_EQ(hmac1, hmac2);
5279}
5280
5281/**
5282 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5283 */
5284TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5285 KeyEvent event = getTestKeyEvent();
5286 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5287 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5288
5289 verifiedEvent.deviceId += 1;
5290 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5291
5292 verifiedEvent.source += 1;
5293 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5294
5295 verifiedEvent.eventTimeNanos += 1;
5296 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5297
5298 verifiedEvent.displayId += 1;
5299 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5300
5301 verifiedEvent.action += 1;
5302 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5303
5304 verifiedEvent.downTimeNanos += 1;
5305 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5306
5307 verifiedEvent.flags += 1;
5308 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5309
5310 verifiedEvent.keyCode += 1;
5311 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5312
5313 verifiedEvent.scanCode += 1;
5314 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5315
5316 verifiedEvent.metaState += 1;
5317 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5318
5319 verifiedEvent.repeatCount += 1;
5320 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5321}
5322
Vishnu Nair958da932020-08-21 17:12:37 -07005323TEST_F(InputDispatcherTest, SetFocusedWindow) {
5324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5325 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005326 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005327 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005328 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005329 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5330
5331 // Top window is also focusable but is not granted focus.
5332 windowTop->setFocusable(true);
5333 windowSecond->setFocusable(true);
5334 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5335 setFocusedWindow(windowSecond);
5336
5337 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5339 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005340
5341 // Focused window should receive event.
5342 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5343 windowTop->assertNoEvents();
5344}
5345
5346TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5347 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5348 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005349 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005350 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5351
5352 window->setFocusable(true);
5353 // Release channel for window is no longer valid.
5354 window->releaseChannel();
5355 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5356 setFocusedWindow(window);
5357
5358 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005359 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5360 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005361
5362 // window channel is invalid, so it should not receive any input event.
5363 window->assertNoEvents();
5364}
5365
5366TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5368 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005369 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005370 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005371 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5372
Vishnu Nair958da932020-08-21 17:12:37 -07005373 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5374 setFocusedWindow(window);
5375
5376 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005377 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5378 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005379
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005380 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005381 window->assertNoEvents();
5382}
5383
5384TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5386 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005387 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005388 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005390 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5391
5392 windowTop->setFocusable(true);
5393 windowSecond->setFocusable(true);
5394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5395 setFocusedWindow(windowTop);
5396 windowTop->consumeFocusEvent(true);
5397
Chavi Weingarten847e8512023-03-29 00:26:09 +00005398 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5399 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005400 windowSecond->consumeFocusEvent(true);
5401 windowTop->consumeFocusEvent(false);
5402
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005403 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5404 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005405
5406 // Focused window should receive event.
5407 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5408}
5409
Chavi Weingarten847e8512023-03-29 00:26:09 +00005410TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5412 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005413 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005414 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005416 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5417
5418 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005419 windowSecond->setFocusable(false);
5420 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005421 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005422 setFocusedWindow(windowTop);
5423 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005424
Chavi Weingarten847e8512023-03-29 00:26:09 +00005425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5426 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005427
5428 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005429 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005430 windowSecond->assertNoEvents();
5431}
5432
5433TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5435 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005436 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005437 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005438 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5439 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005440 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5441
5442 window->setFocusable(true);
5443 previousFocusedWindow->setFocusable(true);
5444 window->setVisible(false);
5445 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5446 setFocusedWindow(previousFocusedWindow);
5447 previousFocusedWindow->consumeFocusEvent(true);
5448
5449 // Requesting focus on invisible window takes focus from currently focused window.
5450 setFocusedWindow(window);
5451 previousFocusedWindow->consumeFocusEvent(false);
5452
5453 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005455 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5456 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005457
5458 // Window does not get focus event or key down.
5459 window->assertNoEvents();
5460
5461 // Window becomes visible.
5462 window->setVisible(true);
5463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5464
5465 // Window receives focus event.
5466 window->consumeFocusEvent(true);
5467 // Focused window receives key down.
5468 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5469}
5470
Vishnu Nair599f1412021-06-21 10:39:58 -07005471TEST_F(InputDispatcherTest, DisplayRemoved) {
5472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5473 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005474 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005475 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5476
5477 // window is granted focus.
5478 window->setFocusable(true);
5479 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5480 setFocusedWindow(window);
5481 window->consumeFocusEvent(true);
5482
5483 // When a display is removed window loses focus.
5484 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5485 window->consumeFocusEvent(false);
5486}
5487
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005488/**
5489 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5490 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5491 * of the 'slipperyEnterWindow'.
5492 *
5493 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5494 * a way so that the touched location is no longer covered by the top window.
5495 *
5496 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5497 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5498 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5499 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5500 * with ACTION_DOWN).
5501 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5502 * window moved itself away from the touched location and had Flag::SLIPPERY.
5503 *
5504 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5505 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5506 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5507 *
5508 * In this test, we ensure that the event received by the bottom window has
5509 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5510 */
5511TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005512 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005513 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005514
5515 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5516 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5517
5518 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005519 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005520 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005521 // Make sure this one overlaps the bottom window
5522 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5523 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5524 // one. Windows with the same owner are not considered to be occluding each other.
5525 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5526
5527 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005528 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005529 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5530
5531 mDispatcher->setInputWindows(
5532 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5533
5534 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005535 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5536 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5537 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005538 slipperyExitWindow->consumeMotionDown();
5539 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5540 mDispatcher->setInputWindows(
5541 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5542
Prabir Pradhan678438e2023-04-13 19:32:51 +00005543 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5544 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5545 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005546
5547 slipperyExitWindow->consumeMotionCancel();
5548
5549 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5550 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5551}
5552
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005553/**
5554 * Two windows, one on the left and another on the right. The left window is slippery. The right
5555 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5556 * touch moves from the left window into the right window, the gesture should continue to go to the
5557 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5558 * reproduces a crash.
5559 */
5560TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5562
5563 sp<FakeWindowHandle> leftSlipperyWindow =
5564 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5565 leftSlipperyWindow->setSlippery(true);
5566 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5567
5568 sp<FakeWindowHandle> rightDropTouchesWindow =
5569 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5570 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5571 rightDropTouchesWindow->setDropInput(true);
5572
5573 mDispatcher->setInputWindows(
5574 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5575
5576 // Start touch in the left window
5577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5578 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5579 .build());
5580 leftSlipperyWindow->consumeMotionDown();
5581
5582 // And move it into the right window
5583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5584 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5585 .build());
5586
5587 // Since the right window isn't eligible to receive input, touch does not slip.
5588 // The left window continues to receive the gesture.
5589 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5590 rightDropTouchesWindow->assertNoEvents();
5591}
5592
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005593TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005594 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5596
5597 sp<FakeWindowHandle> leftWindow =
5598 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5599 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005600 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005601
5602 sp<FakeWindowHandle> rightSpy =
5603 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5604 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005605 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005606 rightSpy->setSpy(true);
5607 rightSpy->setTrustedOverlay(true);
5608
5609 sp<FakeWindowHandle> rightWindow =
5610 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5611 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005612 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005613
5614 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5615
5616 // Touch in the left window
5617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5618 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5619 .build());
5620 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5621 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005622 ASSERT_NO_FATAL_FAILURE(
5623 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005624
5625 // Touch another finger over the right windows
5626 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5627 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5628 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5629 .build());
5630 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5631 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5632 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5633 mDispatcher->waitForIdle();
5634 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005635 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5636 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005637
5638 // Release finger over left window. The UP actions are not treated as device interaction.
5639 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5640 // is part of the UP action, we do not treat this as device interaction.
5641 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5642 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5643 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5644 .build());
5645 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5646 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5647 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5648 mDispatcher->waitForIdle();
5649 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5650
5651 // Move remaining finger
5652 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5653 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5654 .build());
5655 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5656 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5657 mDispatcher->waitForIdle();
5658 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005659 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005660
5661 // Release all fingers
5662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5663 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5664 .build());
5665 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5666 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5667 mDispatcher->waitForIdle();
5668 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5669}
5670
5671TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5673
5674 sp<FakeWindowHandle> window =
5675 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5676 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005677 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005678
5679 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5680 setFocusedWindow(window);
5681 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5682
5683 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5684 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5685 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005686 ASSERT_NO_FATAL_FAILURE(
5687 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005688
5689 // The UP actions are not treated as device interaction.
5690 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5691 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5692 mDispatcher->waitForIdle();
5693 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5694}
5695
Garfield Tan1c7bc862020-01-28 13:24:04 -08005696class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5697protected:
5698 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5699 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5700
Chris Yea209fde2020-07-22 13:54:51 -07005701 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005702 sp<FakeWindowHandle> mWindow;
5703
5704 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005705 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005706 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005707 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005708 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005709 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5710 ASSERT_EQ(OK, mDispatcher->start());
5711
5712 setUpWindow();
5713 }
5714
5715 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005716 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005717 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005718
Vishnu Nair47074b82020-08-14 11:54:47 -07005719 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005721 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005722 mWindow->consumeFocusEvent(true);
5723 }
5724
Chris Ye2ad95392020-09-01 13:44:44 -07005725 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005726 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005727 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005728 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005729 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005730
5731 // Window should receive key down event.
5732 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5733 }
5734
5735 void expectKeyRepeatOnce(int32_t repeatCount) {
5736 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5737 InputEvent* repeatEvent = mWindow->consume();
5738 ASSERT_NE(nullptr, repeatEvent);
5739
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005740 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005741
5742 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5743 uint32_t eventAction = repeatKeyEvent->getAction();
5744 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5745 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5746 }
5747
Chris Ye2ad95392020-09-01 13:44:44 -07005748 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005749 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005750 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005751 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005752 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005753
5754 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005755 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005756 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005757 }
5758};
5759
5760TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005761 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005762 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5763 expectKeyRepeatOnce(repeatCount);
5764 }
5765}
5766
5767TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005768 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005769 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5770 expectKeyRepeatOnce(repeatCount);
5771 }
Harry Cutts33476232023-01-30 19:57:29 +00005772 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005773 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005774 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5775 expectKeyRepeatOnce(repeatCount);
5776 }
5777}
5778
5779TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005780 sendAndConsumeKeyDown(/*deviceId=*/1);
5781 expectKeyRepeatOnce(/*repeatCount=*/1);
5782 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005783 mWindow->assertNoEvents();
5784}
5785
5786TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005787 sendAndConsumeKeyDown(/*deviceId=*/1);
5788 expectKeyRepeatOnce(/*repeatCount=*/1);
5789 sendAndConsumeKeyDown(/*deviceId=*/2);
5790 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005791 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005792 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005793 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005794 expectKeyRepeatOnce(/*repeatCount=*/2);
5795 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005796 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005797 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005798 mWindow->assertNoEvents();
5799}
5800
5801TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005802 sendAndConsumeKeyDown(/*deviceId=*/1);
5803 expectKeyRepeatOnce(/*repeatCount=*/1);
5804 sendAndConsumeKeyDown(/*deviceId=*/2);
5805 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005806 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005807 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005808 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005809 mWindow->assertNoEvents();
5810}
5811
liushenxiang42232912021-05-21 20:24:09 +08005812TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5813 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005814 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005815 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005816 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5817 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5818 mWindow->assertNoEvents();
5819}
5820
Garfield Tan1c7bc862020-01-28 13:24:04 -08005821TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005822 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005823 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005824 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5825 InputEvent* repeatEvent = mWindow->consume();
5826 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5827 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5828 IdGenerator::getSource(repeatEvent->getId()));
5829 }
5830}
5831
5832TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005833 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005834 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005835
5836 std::unordered_set<int32_t> idSet;
5837 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5838 InputEvent* repeatEvent = mWindow->consume();
5839 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5840 int32_t id = repeatEvent->getId();
5841 EXPECT_EQ(idSet.end(), idSet.find(id));
5842 idSet.insert(id);
5843 }
5844}
5845
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005846/* Test InputDispatcher for MultiDisplay */
5847class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5848public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005849 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005850 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005851
Chris Yea209fde2020-07-22 13:54:51 -07005852 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005853 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005854 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005855
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005856 // Set focus window for primary display, but focused display would be second one.
5857 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005858 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005859 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005860 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005861 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005862
Chris Yea209fde2020-07-22 13:54:51 -07005863 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005864 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005865 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005866 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005867 // Set focus display to second one.
5868 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5869 // Set focus window for second display.
5870 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005871 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005872 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005873 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005874 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 }
5876
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005877 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005878 InputDispatcherTest::TearDown();
5879
Chris Yea209fde2020-07-22 13:54:51 -07005880 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005881 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005882 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005883 windowInSecondary.clear();
5884 }
5885
5886protected:
Chris Yea209fde2020-07-22 13:54:51 -07005887 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005888 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005889 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005890 sp<FakeWindowHandle> windowInSecondary;
5891};
5892
5893TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5894 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5896 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005898 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005899 windowInSecondary->assertNoEvents();
5900
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005901 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5903 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005905 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005906 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005907}
5908
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005909TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005910 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5912 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005914 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005915 windowInSecondary->assertNoEvents();
5916
5917 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005919 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005920 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005921 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005922
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005923 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005924 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005925
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005926 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005927 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005928 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005929
5930 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005931 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005932 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005933 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005934 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005935 windowInSecondary->assertNoEvents();
5936}
5937
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005938// Test per-display input monitors for motion event.
5939TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005940 FakeMonitorReceiver monitorInPrimary =
5941 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5942 FakeMonitorReceiver monitorInSecondary =
5943 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005944
5945 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5947 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5948 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005949 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005950 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005951 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005952 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005953
5954 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5956 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005958 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005959 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005960 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005961 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005962
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005963 // Lift up the touch from the second display
5964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5965 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5966 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5967 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5968 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5969
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005970 // Test inject a non-pointer motion event.
5971 // If specific a display, it will dispatch to the focused window of particular display,
5972 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5974 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5975 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005976 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005977 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005978 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005979 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005980}
5981
5982// Test per-display input monitors for key event.
5983TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005984 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005985 FakeMonitorReceiver monitorInPrimary =
5986 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5987 FakeMonitorReceiver monitorInSecondary =
5988 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005989
5990 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5992 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005993 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005994 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005995 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005996 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005997}
5998
Vishnu Nair958da932020-08-21 17:12:37 -07005999TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6000 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006001 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006002 secondWindowInPrimary->setFocusable(true);
6003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6004 setFocusedWindow(secondWindowInPrimary);
6005 windowInPrimary->consumeFocusEvent(false);
6006 secondWindowInPrimary->consumeFocusEvent(true);
6007
6008 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6010 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006011 windowInPrimary->assertNoEvents();
6012 windowInSecondary->assertNoEvents();
6013 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6014}
6015
Arthur Hungdfd528e2021-12-08 13:23:04 +00006016TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6017 FakeMonitorReceiver monitorInPrimary =
6018 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6019 FakeMonitorReceiver monitorInSecondary =
6020 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6021
6022 // Test touch down on primary display.
6023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6024 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6026 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6027 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6028
6029 // Test touch down on second display.
6030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6031 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6033 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6034 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6035
6036 // Trigger cancel touch.
6037 mDispatcher->cancelCurrentTouch();
6038 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6039 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6040 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6041 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6042
6043 // Test inject a move motion event, no window/monitor should receive the event.
6044 ASSERT_EQ(InputEventInjectionResult::FAILED,
6045 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6046 ADISPLAY_ID_DEFAULT, {110, 200}))
6047 << "Inject motion event should return InputEventInjectionResult::FAILED";
6048 windowInPrimary->assertNoEvents();
6049 monitorInPrimary.assertNoEvents();
6050
6051 ASSERT_EQ(InputEventInjectionResult::FAILED,
6052 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6053 SECOND_DISPLAY_ID, {110, 200}))
6054 << "Inject motion event should return InputEventInjectionResult::FAILED";
6055 windowInSecondary->assertNoEvents();
6056 monitorInSecondary.assertNoEvents();
6057}
6058
Jackal Guof9696682018-10-05 12:23:23 +08006059class InputFilterTest : public InputDispatcherTest {
6060protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006061 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6062 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006063 NotifyMotionArgs motionArgs;
6064
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006065 motionArgs =
6066 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006067 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006068 motionArgs =
6069 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006070 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006071 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006072 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006073 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006074 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006075 } else {
6076 mFakePolicy->assertFilterInputEventWasNotCalled();
6077 }
6078 }
6079
6080 void testNotifyKey(bool expectToBeFiltered) {
6081 NotifyKeyArgs keyArgs;
6082
6083 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006084 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006085 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006086 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006087 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006088
6089 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006090 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006091 } else {
6092 mFakePolicy->assertFilterInputEventWasNotCalled();
6093 }
6094 }
6095};
6096
6097// Test InputFilter for MotionEvent
6098TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6099 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6100 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6101 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6102
6103 // Enable InputFilter
6104 mDispatcher->setInputFilterEnabled(true);
6105 // Test touch on both primary and second display, and check if both events are filtered.
6106 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6107 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6108
6109 // Disable InputFilter
6110 mDispatcher->setInputFilterEnabled(false);
6111 // Test touch on both primary and second display, and check if both events aren't filtered.
6112 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6113 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6114}
6115
6116// Test InputFilter for KeyEvent
6117TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6118 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6119 testNotifyKey(/*expectToBeFiltered*/ false);
6120
6121 // Enable InputFilter
6122 mDispatcher->setInputFilterEnabled(true);
6123 // Send a key event, and check if it is filtered.
6124 testNotifyKey(/*expectToBeFiltered*/ true);
6125
6126 // Disable InputFilter
6127 mDispatcher->setInputFilterEnabled(false);
6128 // Send a key event, and check if it isn't filtered.
6129 testNotifyKey(/*expectToBeFiltered*/ false);
6130}
6131
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006132// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6133// logical display coordinate space.
6134TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6135 ui::Transform firstDisplayTransform;
6136 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6137 ui::Transform secondDisplayTransform;
6138 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6139
6140 std::vector<gui::DisplayInfo> displayInfos(2);
6141 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6142 displayInfos[0].transform = firstDisplayTransform;
6143 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6144 displayInfos[1].transform = secondDisplayTransform;
6145
Patrick Williamsd828f302023-04-28 17:52:08 -05006146 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006147
6148 // Enable InputFilter
6149 mDispatcher->setInputFilterEnabled(true);
6150
6151 // Ensure the correct transforms are used for the displays.
6152 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6153 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6154}
6155
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006156class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6157protected:
6158 virtual void SetUp() override {
6159 InputDispatcherTest::SetUp();
6160
6161 /**
6162 * We don't need to enable input filter to test the injected event policy, but we enabled it
6163 * here to make the tests more realistic, since this policy only matters when inputfilter is
6164 * on.
6165 */
6166 mDispatcher->setInputFilterEnabled(true);
6167
6168 std::shared_ptr<InputApplicationHandle> application =
6169 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006170 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6171 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006172
6173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6174 mWindow->setFocusable(true);
6175 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6176 setFocusedWindow(mWindow);
6177 mWindow->consumeFocusEvent(true);
6178 }
6179
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006180 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6181 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006182 KeyEvent event;
6183
6184 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6185 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6186 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006187 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006188 const int32_t additionalPolicyFlags =
6189 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006191 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006192 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6193 policyFlags | additionalPolicyFlags));
6194
6195 InputEvent* received = mWindow->consume();
6196 ASSERT_NE(nullptr, received);
6197 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006198 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006199 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6200 ASSERT_EQ(flags, keyEvent.getFlags());
6201 }
6202
6203 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6204 int32_t flags) {
6205 MotionEvent event;
6206 PointerProperties pointerProperties[1];
6207 PointerCoords pointerCoords[1];
6208 pointerProperties[0].clear();
6209 pointerProperties[0].id = 0;
6210 pointerCoords[0].clear();
6211 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6212 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6213
6214 ui::Transform identityTransform;
6215 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6216 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6217 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6218 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6219 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006220 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006221 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006222 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6223
6224 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006226 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006227 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6228 policyFlags | additionalPolicyFlags));
6229
6230 InputEvent* received = mWindow->consume();
6231 ASSERT_NE(nullptr, received);
6232 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006233 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006234 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6235 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006236 }
6237
6238private:
6239 sp<FakeWindowHandle> mWindow;
6240};
6241
6242TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006243 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6244 // filter. Without it, the event will no different from a regularly injected event, and the
6245 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006246 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6247 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006248}
6249
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006250TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006251 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006252 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006253 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6254}
6255
6256TEST_F(InputFilterInjectionPolicyTest,
6257 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6258 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006259 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006260 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006261}
6262
6263TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006264 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6265 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006266}
6267
chaviwfd6d3512019-03-25 13:23:49 -07006268class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006269 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006270 InputDispatcherTest::SetUp();
6271
Chris Yea209fde2020-07-22 13:54:51 -07006272 std::shared_ptr<FakeApplicationHandle> application =
6273 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006274 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006275 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006276 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006277
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006278 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006279 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006280 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006281
6282 // Set focused application.
6283 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006284 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006285
6286 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006288 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006289 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006290 }
6291
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006292 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006293 InputDispatcherTest::TearDown();
6294
6295 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006296 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006297 }
6298
6299protected:
6300 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006301 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006302 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006303};
6304
6305// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6306// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6307// the onPointerDownOutsideFocus callback.
6308TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006310 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6311 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006313 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006314
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006315 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006316 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6317}
6318
6319// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6320// DOWN on the window that doesn't have focus. Ensure no window received the
6321// onPointerDownOutsideFocus callback.
6322TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006324 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006326 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006327
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006328 ASSERT_TRUE(mDispatcher->waitForIdle());
6329 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006330}
6331
6332// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6333// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6334TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6336 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006337 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006338 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006339
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006340 ASSERT_TRUE(mDispatcher->waitForIdle());
6341 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006342}
6343
6344// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6345// DOWN on the window that already has focus. Ensure no window received the
6346// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006347TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006349 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006350 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006352 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006353
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006354 ASSERT_TRUE(mDispatcher->waitForIdle());
6355 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006356}
6357
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006358// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6359// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6360TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6361 const MotionEvent event =
6362 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6363 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006364 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006365 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6366 .build();
6367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6368 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6369 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6370
6371 ASSERT_TRUE(mDispatcher->waitForIdle());
6372 mFakePolicy->assertOnPointerDownWasNotCalled();
6373 // Ensure that the unfocused window did not receive any FOCUS events.
6374 mUnfocusedWindow->assertNoEvents();
6375}
6376
chaviwaf87b3e2019-10-01 16:59:28 -07006377// These tests ensures we can send touch events to a single client when there are multiple input
6378// windows that point to the same client token.
6379class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6380 virtual void SetUp() override {
6381 InputDispatcherTest::SetUp();
6382
Chris Yea209fde2020-07-22 13:54:51 -07006383 std::shared_ptr<FakeApplicationHandle> application =
6384 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006385 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6386 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006387 mWindow1->setFrame(Rect(0, 0, 100, 100));
6388
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006389 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6390 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006391 mWindow2->setFrame(Rect(100, 100, 200, 200));
6392
Arthur Hung72d8dc32020-03-28 00:48:39 +00006393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006394 }
6395
6396protected:
6397 sp<FakeWindowHandle> mWindow1;
6398 sp<FakeWindowHandle> mWindow2;
6399
6400 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006401 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006402 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6403 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006404 }
6405
6406 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6407 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006408 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006409 InputEvent* event = window->consume();
6410
6411 ASSERT_NE(nullptr, event) << name.c_str()
6412 << ": consumer should have returned non-NULL event.";
6413
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006414 ASSERT_EQ(InputEventType::MOTION, event->getType())
6415 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006416
6417 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006418 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006419 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006420
6421 for (size_t i = 0; i < points.size(); i++) {
6422 float expectedX = points[i].x;
6423 float expectedY = points[i].y;
6424
6425 EXPECT_EQ(expectedX, motionEvent.getX(i))
6426 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6427 << ", got " << motionEvent.getX(i);
6428 EXPECT_EQ(expectedY, motionEvent.getY(i))
6429 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6430 << ", got " << motionEvent.getY(i);
6431 }
6432 }
chaviw9eaa22c2020-07-01 16:21:27 -07006433
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006434 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006435 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006436 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6437 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006438
6439 // Always consume from window1 since it's the window that has the InputReceiver
6440 consumeMotionEvent(mWindow1, action, expectedPoints);
6441 }
chaviwaf87b3e2019-10-01 16:59:28 -07006442};
6443
6444TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6445 // Touch Window 1
6446 PointF touchedPoint = {10, 10};
6447 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006448 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006449
6450 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006451 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006452
6453 // Touch Window 2
6454 touchedPoint = {150, 150};
6455 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006456 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006457}
6458
chaviw9eaa22c2020-07-01 16:21:27 -07006459TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6460 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006461 mWindow2->setWindowScale(0.5f, 0.5f);
6462
6463 // Touch Window 1
6464 PointF touchedPoint = {10, 10};
6465 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006466 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006467 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006468 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006469
6470 // Touch Window 2
6471 touchedPoint = {150, 150};
6472 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006473 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6474 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006475
chaviw9eaa22c2020-07-01 16:21:27 -07006476 // Update the transform so rotation is set
6477 mWindow2->setWindowTransform(0, -1, 1, 0);
6478 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6479 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006480}
6481
chaviw9eaa22c2020-07-01 16:21:27 -07006482TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006483 mWindow2->setWindowScale(0.5f, 0.5f);
6484
6485 // Touch Window 1
6486 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6487 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006488 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006489
6490 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006491 touchedPoints.push_back(PointF{150, 150});
6492 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006493 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006494
chaviw9eaa22c2020-07-01 16:21:27 -07006495 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006496 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006497 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006498
chaviw9eaa22c2020-07-01 16:21:27 -07006499 // Update the transform so rotation is set for Window 2
6500 mWindow2->setWindowTransform(0, -1, 1, 0);
6501 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006502 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006503}
6504
chaviw9eaa22c2020-07-01 16:21:27 -07006505TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006506 mWindow2->setWindowScale(0.5f, 0.5f);
6507
6508 // Touch Window 1
6509 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6510 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006511 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006512
6513 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006514 touchedPoints.push_back(PointF{150, 150});
6515 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006516
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006517 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006518
6519 // Move both windows
6520 touchedPoints = {{20, 20}, {175, 175}};
6521 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6522 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6523
chaviw9eaa22c2020-07-01 16:21:27 -07006524 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006525
chaviw9eaa22c2020-07-01 16:21:27 -07006526 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006527 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006528 expectedPoints.pop_back();
6529
6530 // Touch Window 2
6531 mWindow2->setWindowTransform(0, -1, 1, 0);
6532 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006533 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006534
6535 // Move both windows
6536 touchedPoints = {{20, 20}, {175, 175}};
6537 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6538 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6539
6540 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006541}
6542
6543TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6544 mWindow1->setWindowScale(0.5f, 0.5f);
6545
6546 // Touch Window 1
6547 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6548 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006549 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006550
6551 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006552 touchedPoints.push_back(PointF{150, 150});
6553 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006554
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006555 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006556
6557 // Move both windows
6558 touchedPoints = {{20, 20}, {175, 175}};
6559 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6560 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6561
chaviw9eaa22c2020-07-01 16:21:27 -07006562 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006563}
6564
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006565/**
6566 * When one of the windows is slippery, the touch should not slip into the other window with the
6567 * same input channel.
6568 */
6569TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6570 mWindow1->setSlippery(true);
6571 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6572
6573 // Touch down in window 1
6574 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6575 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6576 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6577
6578 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6579 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6580 // getting generated.
6581 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6582 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6583
6584 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6585}
6586
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006587/**
6588 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6589 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6590 * that the pointer is hovering over may have a different transform.
6591 */
6592TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6593 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6594
6595 // Start hover in window 1
6596 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6597 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6598 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6599 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6600
6601 // Move hover to window 2.
6602 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6603 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6604
6605 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6606 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6607 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6608}
6609
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006610class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6611 virtual void SetUp() override {
6612 InputDispatcherTest::SetUp();
6613
Chris Yea209fde2020-07-22 13:54:51 -07006614 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006615 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006616 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6617 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006618 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006619 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006620 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006621
6622 // Set focused application.
6623 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6624
6625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006626 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006627 mWindow->consumeFocusEvent(true);
6628 }
6629
6630 virtual void TearDown() override {
6631 InputDispatcherTest::TearDown();
6632 mWindow.clear();
6633 }
6634
6635protected:
Chris Yea209fde2020-07-22 13:54:51 -07006636 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006637 sp<FakeWindowHandle> mWindow;
6638 static constexpr PointF WINDOW_LOCATION = {20, 20};
6639
6640 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006642 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6643 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006645 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6646 WINDOW_LOCATION));
6647 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006648
6649 sp<FakeWindowHandle> addSpyWindow() {
6650 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006651 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006652 spy->setTrustedOverlay(true);
6653 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006654 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006655 spy->setDispatchingTimeout(30ms);
6656 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6657 return spy;
6658 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006659};
6660
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006661// Send a tap and respond, which should not cause an ANR.
6662TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6663 tapOnWindow();
6664 mWindow->consumeMotionDown();
6665 mWindow->consumeMotionUp();
6666 ASSERT_TRUE(mDispatcher->waitForIdle());
6667 mFakePolicy->assertNotifyAnrWasNotCalled();
6668}
6669
6670// Send a regular key and respond, which should not cause an ANR.
6671TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006673 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6674 ASSERT_TRUE(mDispatcher->waitForIdle());
6675 mFakePolicy->assertNotifyAnrWasNotCalled();
6676}
6677
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006678TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6679 mWindow->setFocusable(false);
6680 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6681 mWindow->consumeFocusEvent(false);
6682
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006683 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006684 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6685 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6686 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006688 // Key will not go to window because we have no focused window.
6689 // The 'no focused window' ANR timer should start instead.
6690
6691 // Now, the focused application goes away.
6692 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6693 // The key should get dropped and there should be no ANR.
6694
6695 ASSERT_TRUE(mDispatcher->waitForIdle());
6696 mFakePolicy->assertNotifyAnrWasNotCalled();
6697}
6698
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006699// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006700// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6701// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006702TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006704 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6705 WINDOW_LOCATION));
6706
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006707 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6708 ASSERT_TRUE(sequenceNum);
6709 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006710 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006711
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006712 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006713 mWindow->consumeMotionEvent(
6714 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006715 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006716 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006717}
6718
6719// Send a key to the app and have the app not respond right away.
6720TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6721 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006722 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006723 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6724 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006725 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006726 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006727 ASSERT_TRUE(mDispatcher->waitForIdle());
6728}
6729
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006730// We have a focused application, but no focused window
6731TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006732 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006733 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6734 mWindow->consumeFocusEvent(false);
6735
6736 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6739 WINDOW_LOCATION));
6740 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6741 mDispatcher->waitForIdle();
6742 mFakePolicy->assertNotifyAnrWasNotCalled();
6743
6744 // Once a focused event arrives, we get an ANR for this application
6745 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6746 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006747 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006748 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6749 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006750 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006751 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006752 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006753 ASSERT_TRUE(mDispatcher->waitForIdle());
6754}
6755
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006756/**
6757 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6758 * there will not be an ANR.
6759 */
6760TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6761 mWindow->setFocusable(false);
6762 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6763 mWindow->consumeFocusEvent(false);
6764
6765 KeyEvent event;
6766 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6767 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6768
6769 // Define a valid key down event that is stale (too old).
6770 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6771 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006772 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006773
6774 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6775
6776 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006777 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006778 InputEventInjectionSync::WAIT_FOR_RESULT,
6779 INJECT_EVENT_TIMEOUT, policyFlags);
6780 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6781 << "Injection should fail because the event is stale";
6782
6783 ASSERT_TRUE(mDispatcher->waitForIdle());
6784 mFakePolicy->assertNotifyAnrWasNotCalled();
6785 mWindow->assertNoEvents();
6786}
6787
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006788// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006789// Make sure that we don't notify policy twice about the same ANR.
6790TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006791 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006792 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6793 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006794
6795 // Once a focused event arrives, we get an ANR for this application
6796 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6797 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006798 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006799 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6800 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006801 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006802 const std::chrono::duration appTimeout =
6803 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6804 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006805
Vishnu Naire4df8752022-09-08 09:17:55 -07006806 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006807 // ANR should not be raised again. It is up to policy to do that if it desires.
6808 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006809
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006810 // If we now get a focused window, the ANR should stop, but the policy handles that via
6811 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006812 ASSERT_TRUE(mDispatcher->waitForIdle());
6813}
6814
6815// We have a focused application, but no focused window
6816TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006817 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6819 mWindow->consumeFocusEvent(false);
6820
6821 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006822 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006823 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006824 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6825 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006826
Vishnu Naire4df8752022-09-08 09:17:55 -07006827 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6828 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006829
6830 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006831 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006832 ASSERT_TRUE(mDispatcher->waitForIdle());
6833 mWindow->assertNoEvents();
6834}
6835
6836/**
6837 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6838 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6839 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6840 * the ANR mechanism should still work.
6841 *
6842 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6843 * DOWN event, while not responding on the second one.
6844 */
6845TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6846 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6847 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6848 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6849 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6850 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006851 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006852
6853 // Now send ACTION_UP, with identical timestamp
6854 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6855 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6856 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6857 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006858 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006859
6860 // We have now sent down and up. Let's consume first event and then ANR on the second.
6861 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6862 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006863 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006864}
6865
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006866// A spy window can receive an ANR
6867TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6868 sp<FakeWindowHandle> spy = addSpyWindow();
6869
6870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6871 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6872 WINDOW_LOCATION));
6873 mWindow->consumeMotionDown();
6874
6875 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6876 ASSERT_TRUE(sequenceNum);
6877 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006878 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006879
6880 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006881 spy->consumeMotionEvent(
6882 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006883 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006884 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006885}
6886
6887// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006889TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6890 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6893 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006894 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006896
6897 // Stuck on the ACTION_UP
6898 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006899 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006900
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006901 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006902 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006903 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6904 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905
6906 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6907 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006908 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006909 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006910 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911}
6912
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006913// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006914// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006915TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6916 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006917
6918 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006919 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6920 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006921
6922 mWindow->consumeMotionDown();
6923 // Stuck on the ACTION_UP
6924 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006925 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006926
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006927 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006928 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006929 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6930 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006931
6932 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6933 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006934 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006935 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006936 spy->assertNoEvents();
6937}
6938
6939TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6940 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6941
6942 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6943
6944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6945 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6946 WINDOW_LOCATION));
6947
6948 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6949 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6950 ASSERT_TRUE(consumeSeq);
6951
Prabir Pradhanedd96402022-02-15 01:46:16 -08006952 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006953
6954 monitor.finishEvent(*consumeSeq);
6955 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6956
6957 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006958 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006959}
6960
6961// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6962// process events, you don't get an anr. When the window later becomes unresponsive again, you
6963// get an ANR again.
6964// 1. tap -> block on ACTION_UP -> receive ANR
6965// 2. consume all pending events (= queue becomes healthy again)
6966// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6967TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6968 tapOnWindow();
6969
6970 mWindow->consumeMotionDown();
6971 // Block on ACTION_UP
6972 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006973 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006974 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6975 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006976 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006977 mWindow->assertNoEvents();
6978
6979 tapOnWindow();
6980 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006981 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006982 mWindow->consumeMotionUp();
6983
6984 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006985 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006986 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006987 mWindow->assertNoEvents();
6988}
6989
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006990// If a connection remains unresponsive for a while, make sure policy is only notified once about
6991// it.
6992TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006993 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006994 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6995 WINDOW_LOCATION));
6996
6997 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006998 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006999 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007000 // 'notifyConnectionUnresponsive' should only be called once per connection
7001 mFakePolicy->assertNotifyAnrWasNotCalled();
7002 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007003 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007004 mWindow->consumeMotionEvent(
7005 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007006 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007007 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007008 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007009 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007010}
7011
7012/**
7013 * If a window is processing a motion event, and then a key event comes in, the key event should
7014 * not to to the focused window until the motion is processed.
7015 *
7016 * Warning!!!
7017 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7018 * and the injection timeout that we specify when injecting the key.
7019 * We must have the injection timeout (10ms) be smaller than
7020 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7021 *
7022 * If that value changes, this test should also change.
7023 */
7024TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7025 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7027
7028 tapOnWindow();
7029 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7030 ASSERT_TRUE(downSequenceNum);
7031 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7032 ASSERT_TRUE(upSequenceNum);
7033 // Don't finish the events yet, and send a key
7034 // Injection will "succeed" because we will eventually give up and send the key to the focused
7035 // window even if motions are still being processed. But because the injection timeout is short,
7036 // we will receive INJECTION_TIMED_OUT as the result.
7037
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007038 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007039 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007040 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7041 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007042 // Key will not be sent to the window, yet, because the window is still processing events
7043 // and the key remains pending, waiting for the touch events to be processed
7044 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7045 ASSERT_FALSE(keySequenceNum);
7046
7047 std::this_thread::sleep_for(500ms);
7048 // if we wait long enough though, dispatcher will give up, and still send the key
7049 // to the focused window, even though we have not yet finished the motion event
7050 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7051 mWindow->finishEvent(*downSequenceNum);
7052 mWindow->finishEvent(*upSequenceNum);
7053}
7054
7055/**
7056 * If a window is processing a motion event, and then a key event comes in, the key event should
7057 * not go to the focused window until the motion is processed.
7058 * If then a new motion comes in, then the pending key event should be going to the currently
7059 * focused window right away.
7060 */
7061TEST_F(InputDispatcherSingleWindowAnr,
7062 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7063 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7064 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7065
7066 tapOnWindow();
7067 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7068 ASSERT_TRUE(downSequenceNum);
7069 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7070 ASSERT_TRUE(upSequenceNum);
7071 // Don't finish the events yet, and send a key
7072 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007074 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7075 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007076 // At this point, key is still pending, and should not be sent to the application yet.
7077 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7078 ASSERT_FALSE(keySequenceNum);
7079
7080 // Now tap down again. It should cause the pending key to go to the focused window right away.
7081 tapOnWindow();
7082 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7083 // the other events yet. We can finish events in any order.
7084 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7085 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7086 mWindow->consumeMotionDown();
7087 mWindow->consumeMotionUp();
7088 mWindow->assertNoEvents();
7089}
7090
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007091/**
7092 * Send an event to the app and have the app not respond right away.
7093 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7094 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7095 * At some point, the window becomes responsive again.
7096 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7097 */
7098TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7100 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7101 .build());
7102
7103 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7104 ASSERT_TRUE(sequenceNum);
7105 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7106 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7107
7108 mWindow->finishEvent(*sequenceNum);
7109 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7110 ASSERT_TRUE(mDispatcher->waitForIdle());
7111 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7112
7113 // Now that the window is responsive, let's continue the gesture.
7114 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7115 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7116 .build());
7117
7118 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7119 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7120 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7121 .build());
7122
7123 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7124 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7125 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7126 .build());
7127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7128 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7129 .build());
7130 // We already canceled this pointer, so the window shouldn't get any new events.
7131 mWindow->assertNoEvents();
7132
7133 // Start another one.
7134 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7135 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7136 .build());
7137 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7138}
7139
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007140class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7141 virtual void SetUp() override {
7142 InputDispatcherTest::SetUp();
7143
Chris Yea209fde2020-07-22 13:54:51 -07007144 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007146 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7147 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007148 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007149 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007150 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007151
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007152 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7153 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007154 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007155 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007156
7157 // Set focused application.
7158 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007159 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007160
7161 // Expect one focus window exist in display.
7162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007163 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007164 mFocusedWindow->consumeFocusEvent(true);
7165 }
7166
7167 virtual void TearDown() override {
7168 InputDispatcherTest::TearDown();
7169
7170 mUnfocusedWindow.clear();
7171 mFocusedWindow.clear();
7172 }
7173
7174protected:
Chris Yea209fde2020-07-22 13:54:51 -07007175 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007176 sp<FakeWindowHandle> mUnfocusedWindow;
7177 sp<FakeWindowHandle> mFocusedWindow;
7178 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7179 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7180 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7181
7182 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7183
7184 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7185
7186private:
7187 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007189 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7190 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007192 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7193 location));
7194 }
7195};
7196
7197// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7198// should be ANR'd first.
7199TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007201 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7202 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007204 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007205 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007206 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007207 // We consumed all events, so no ANR
7208 ASSERT_TRUE(mDispatcher->waitForIdle());
7209 mFakePolicy->assertNotifyAnrWasNotCalled();
7210
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007212 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7213 FOCUSED_WINDOW_LOCATION));
7214 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7215 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007216
7217 const std::chrono::duration timeout =
7218 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007219 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007220 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7221 // sequence to make it consistent
7222 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007223 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007224 mFocusedWindow->consumeMotionDown();
7225 // This cancel is generated because the connection was unresponsive
7226 mFocusedWindow->consumeMotionCancel();
7227 mFocusedWindow->assertNoEvents();
7228 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007229 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007230 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7231 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007232 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007233}
7234
7235// If we have 2 windows with identical timeouts that are both unresponsive,
7236// it doesn't matter which order they should have ANR.
7237// But we should receive ANR for both.
7238TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7239 // Set the timeout for unfocused window to match the focused window
7240 mUnfocusedWindow->setDispatchingTimeout(10ms);
7241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7242
7243 tapOnFocusedWindow();
7244 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007245 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7246 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7247 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007248
7249 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007250 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7251 mFocusedWindow->getToken() == anrConnectionToken2);
7252 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7253 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007254
7255 ASSERT_TRUE(mDispatcher->waitForIdle());
7256 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007257
7258 mFocusedWindow->consumeMotionDown();
7259 mFocusedWindow->consumeMotionUp();
7260 mUnfocusedWindow->consumeMotionOutside();
7261
Prabir Pradhanedd96402022-02-15 01:46:16 -08007262 sp<IBinder> responsiveToken1, responsiveToken2;
7263 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7264 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007265
7266 // Both applications should be marked as responsive, in any order
7267 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7268 mFocusedWindow->getToken() == responsiveToken2);
7269 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7270 mUnfocusedWindow->getToken() == responsiveToken2);
7271 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007272}
7273
7274// If a window is already not responding, the second tap on the same window should be ignored.
7275// We should also log an error to account for the dropped event (not tested here).
7276// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7277TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7278 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007279 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007280 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007281 // Receive the events, but don't respond
7282 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7283 ASSERT_TRUE(downEventSequenceNum);
7284 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7285 ASSERT_TRUE(upEventSequenceNum);
7286 const std::chrono::duration timeout =
7287 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007288 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007289
7290 // Tap once again
7291 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007292 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007293 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7294 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007295 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007296 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7297 FOCUSED_WINDOW_LOCATION));
7298 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7299 // valid touch target
7300 mUnfocusedWindow->assertNoEvents();
7301
7302 // Consume the first tap
7303 mFocusedWindow->finishEvent(*downEventSequenceNum);
7304 mFocusedWindow->finishEvent(*upEventSequenceNum);
7305 ASSERT_TRUE(mDispatcher->waitForIdle());
7306 // The second tap did not go to the focused window
7307 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007308 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007309 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7310 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007311 mFakePolicy->assertNotifyAnrWasNotCalled();
7312}
7313
7314// If you tap outside of all windows, there will not be ANR
7315TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007317 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7318 LOCATION_OUTSIDE_ALL_WINDOWS));
7319 ASSERT_TRUE(mDispatcher->waitForIdle());
7320 mFakePolicy->assertNotifyAnrWasNotCalled();
7321}
7322
7323// Since the focused window is paused, tapping on it should not produce any events
7324TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7325 mFocusedWindow->setPaused(true);
7326 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7327
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007329 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7330 FOCUSED_WINDOW_LOCATION));
7331
7332 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7333 ASSERT_TRUE(mDispatcher->waitForIdle());
7334 // Should not ANR because the window is paused, and touches shouldn't go to it
7335 mFakePolicy->assertNotifyAnrWasNotCalled();
7336
7337 mFocusedWindow->assertNoEvents();
7338 mUnfocusedWindow->assertNoEvents();
7339}
7340
7341/**
7342 * If a window is processing a motion event, and then a key event comes in, the key event should
7343 * not to to the focused window until the motion is processed.
7344 * If a different window becomes focused at this time, the key should go to that window instead.
7345 *
7346 * Warning!!!
7347 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7348 * and the injection timeout that we specify when injecting the key.
7349 * We must have the injection timeout (10ms) be smaller than
7350 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7351 *
7352 * If that value changes, this test should also change.
7353 */
7354TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7355 // Set a long ANR timeout to prevent it from triggering
7356 mFocusedWindow->setDispatchingTimeout(2s);
7357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7358
7359 tapOnUnfocusedWindow();
7360 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7361 ASSERT_TRUE(downSequenceNum);
7362 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7363 ASSERT_TRUE(upSequenceNum);
7364 // Don't finish the events yet, and send a key
7365 // Injection will succeed because we will eventually give up and send the key to the focused
7366 // window even if motions are still being processed.
7367
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007368 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007369 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7370 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372 // Key will not be sent to the window, yet, because the window is still processing events
7373 // and the key remains pending, waiting for the touch events to be processed
7374 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7375 ASSERT_FALSE(keySequenceNum);
7376
7377 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007378 mFocusedWindow->setFocusable(false);
7379 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007380 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007381 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007382
7383 // Focus events should precede the key events
7384 mUnfocusedWindow->consumeFocusEvent(true);
7385 mFocusedWindow->consumeFocusEvent(false);
7386
7387 // Finish the tap events, which should unblock dispatcher
7388 mUnfocusedWindow->finishEvent(*downSequenceNum);
7389 mUnfocusedWindow->finishEvent(*upSequenceNum);
7390
7391 // Now that all queues are cleared and no backlog in the connections, the key event
7392 // can finally go to the newly focused "mUnfocusedWindow".
7393 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7394 mFocusedWindow->assertNoEvents();
7395 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007396 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007397}
7398
7399// When the touch stream is split across 2 windows, and one of them does not respond,
7400// then ANR should be raised and the touch should be canceled for the unresponsive window.
7401// The other window should not be affected by that.
7402TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7403 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007404 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7405 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7406 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007407 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007408 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409
7410 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007411 mDispatcher->notifyMotion(
7412 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7413 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414
7415 const std::chrono::duration timeout =
7416 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007417 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007418
7419 mUnfocusedWindow->consumeMotionDown();
7420 mFocusedWindow->consumeMotionDown();
7421 // Focused window may or may not receive ACTION_MOVE
7422 // But it should definitely receive ACTION_CANCEL due to the ANR
7423 InputEvent* event;
7424 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7425 ASSERT_TRUE(moveOrCancelSequenceNum);
7426 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7427 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007428 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007429 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7430 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7431 mFocusedWindow->consumeMotionCancel();
7432 } else {
7433 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7434 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007435 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007436 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7437 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007438
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439 mUnfocusedWindow->assertNoEvents();
7440 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007441 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007442}
7443
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007444/**
7445 * If we have no focused window, and a key comes in, we start the ANR timer.
7446 * The focused application should add a focused window before the timer runs out to prevent ANR.
7447 *
7448 * If the user touches another application during this time, the key should be dropped.
7449 * Next, if a new focused window comes in, without toggling the focused application,
7450 * then no ANR should occur.
7451 *
7452 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7453 * but in some cases the policy may not update the focused application.
7454 */
7455TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7456 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7457 std::make_shared<FakeApplicationHandle>();
7458 focusedApplication->setDispatchingTimeout(60ms);
7459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7460 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7461 mFocusedWindow->setFocusable(false);
7462
7463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7464 mFocusedWindow->consumeFocusEvent(false);
7465
7466 // Send a key. The ANR timer should start because there is no focused window.
7467 // 'focusedApplication' will get blamed if this timer completes.
7468 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007470 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7471 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7472 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007474
7475 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7476 // then the injected touches won't cause the focused event to get dropped.
7477 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7478 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7479 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7480 // For this test, it means that the key would get delivered to the window once it becomes
7481 // focused.
7482 std::this_thread::sleep_for(10ms);
7483
7484 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007485 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7486 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7487 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007488
7489 // We do not consume the motion right away, because that would require dispatcher to first
7490 // process (== drop) the key event, and by that time, ANR will be raised.
7491 // Set the focused window first.
7492 mFocusedWindow->setFocusable(true);
7493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7494 setFocusedWindow(mFocusedWindow);
7495 mFocusedWindow->consumeFocusEvent(true);
7496 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7497 // to another application. This could be a bug / behaviour in the policy.
7498
7499 mUnfocusedWindow->consumeMotionDown();
7500
7501 ASSERT_TRUE(mDispatcher->waitForIdle());
7502 // Should not ANR because we actually have a focused window. It was just added too slowly.
7503 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7504}
7505
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007506// These tests ensure we cannot send touch events to a window that's positioned behind a window
7507// that has feature NO_INPUT_CHANNEL.
7508// Layout:
7509// Top (closest to user)
7510// mNoInputWindow (above all windows)
7511// mBottomWindow
7512// Bottom (furthest from user)
7513class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7514 virtual void SetUp() override {
7515 InputDispatcherTest::SetUp();
7516
7517 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007518 mNoInputWindow =
7519 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7520 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007521 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007522 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007523 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7524 // It's perfectly valid for this window to not have an associated input channel
7525
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007526 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7527 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007528 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7529
7530 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7531 }
7532
7533protected:
7534 std::shared_ptr<FakeApplicationHandle> mApplication;
7535 sp<FakeWindowHandle> mNoInputWindow;
7536 sp<FakeWindowHandle> mBottomWindow;
7537};
7538
7539TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7540 PointF touchedPoint = {10, 10};
7541
Prabir Pradhan678438e2023-04-13 19:32:51 +00007542 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7543 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7544 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007545
7546 mNoInputWindow->assertNoEvents();
7547 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7548 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7549 // and therefore should prevent mBottomWindow from receiving touches
7550 mBottomWindow->assertNoEvents();
7551}
7552
7553/**
7554 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7555 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7556 */
7557TEST_F(InputDispatcherMultiWindowOcclusionTests,
7558 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007559 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7560 "Window with input channel and NO_INPUT_CHANNEL",
7561 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007562
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007563 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007564 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7566
7567 PointF touchedPoint = {10, 10};
7568
Prabir Pradhan678438e2023-04-13 19:32:51 +00007569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7571 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007572
7573 mNoInputWindow->assertNoEvents();
7574 mBottomWindow->assertNoEvents();
7575}
7576
Vishnu Nair958da932020-08-21 17:12:37 -07007577class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7578protected:
7579 std::shared_ptr<FakeApplicationHandle> mApp;
7580 sp<FakeWindowHandle> mWindow;
7581 sp<FakeWindowHandle> mMirror;
7582
7583 virtual void SetUp() override {
7584 InputDispatcherTest::SetUp();
7585 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007586 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7587 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7588 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007589 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7590 mWindow->setFocusable(true);
7591 mMirror->setFocusable(true);
7592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7593 }
7594};
7595
7596TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7597 // Request focus on a mirrored window
7598 setFocusedWindow(mMirror);
7599
7600 // window gets focused
7601 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7603 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007604 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7605}
7606
7607// A focused & mirrored window remains focused only if the window and its mirror are both
7608// focusable.
7609TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7610 setFocusedWindow(mMirror);
7611
7612 // window gets focused
7613 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007616 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7618 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007619 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7620
7621 mMirror->setFocusable(false);
7622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7623
7624 // window loses focus since one of the windows associated with the token in not focusable
7625 mWindow->consumeFocusEvent(false);
7626
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7628 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007629 mWindow->assertNoEvents();
7630}
7631
7632// A focused & mirrored window remains focused until the window and its mirror both become
7633// invisible.
7634TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7635 setFocusedWindow(mMirror);
7636
7637 // window gets focused
7638 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7640 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007641 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7643 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007644 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7645
7646 mMirror->setVisible(false);
7647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7648
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7650 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007651 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7653 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007654 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7655
7656 mWindow->setVisible(false);
7657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7658
7659 // window loses focus only after all windows associated with the token become invisible.
7660 mWindow->consumeFocusEvent(false);
7661
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007662 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7663 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007664 mWindow->assertNoEvents();
7665}
7666
7667// A focused & mirrored window remains focused until both windows are removed.
7668TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7669 setFocusedWindow(mMirror);
7670
7671 // window gets focused
7672 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7674 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007675 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7677 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007678 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7679
7680 // single window is removed but the window token remains focused
7681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7682
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007685 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7687 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007688 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7689
7690 // Both windows are removed
7691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7692 mWindow->consumeFocusEvent(false);
7693
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7695 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007696 mWindow->assertNoEvents();
7697}
7698
7699// Focus request can be pending until one window becomes visible.
7700TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7701 // Request focus on an invisible mirror.
7702 mWindow->setVisible(false);
7703 mMirror->setVisible(false);
7704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7705 setFocusedWindow(mMirror);
7706
7707 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007709 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7710 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007711
7712 mMirror->setVisible(true);
7713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7714
7715 // window gets focused
7716 mWindow->consumeFocusEvent(true);
7717 // window gets the pending key event
7718 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7719}
Prabir Pradhan99987712020-11-10 18:43:05 -08007720
7721class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7722protected:
7723 std::shared_ptr<FakeApplicationHandle> mApp;
7724 sp<FakeWindowHandle> mWindow;
7725 sp<FakeWindowHandle> mSecondWindow;
7726
7727 void SetUp() override {
7728 InputDispatcherTest::SetUp();
7729 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007730 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007731 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007732 mSecondWindow =
7733 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007734 mSecondWindow->setFocusable(true);
7735
7736 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7738
7739 setFocusedWindow(mWindow);
7740 mWindow->consumeFocusEvent(true);
7741 }
7742
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007743 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007744 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007745 }
7746
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007747 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7748 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007749 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007750 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7751 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007752 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007753 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007754 }
7755};
7756
7757TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7758 // Ensure that capture cannot be obtained for unfocused windows.
7759 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7760 mFakePolicy->assertSetPointerCaptureNotCalled();
7761 mSecondWindow->assertNoEvents();
7762
7763 // Ensure that capture can be enabled from the focus window.
7764 requestAndVerifyPointerCapture(mWindow, true);
7765
7766 // Ensure that capture cannot be disabled from a window that does not have capture.
7767 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7768 mFakePolicy->assertSetPointerCaptureNotCalled();
7769
7770 // Ensure that capture can be disabled from the window with capture.
7771 requestAndVerifyPointerCapture(mWindow, false);
7772}
7773
7774TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007775 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007776
7777 setFocusedWindow(mSecondWindow);
7778
7779 // Ensure that the capture disabled event was sent first.
7780 mWindow->consumeCaptureEvent(false);
7781 mWindow->consumeFocusEvent(false);
7782 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007783 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007784
7785 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007786 notifyPointerCaptureChanged({});
7787 notifyPointerCaptureChanged(request);
7788 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007789 mWindow->assertNoEvents();
7790 mSecondWindow->assertNoEvents();
7791 mFakePolicy->assertSetPointerCaptureNotCalled();
7792}
7793
7794TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007795 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007796
7797 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007798 notifyPointerCaptureChanged({});
7799 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007800
7801 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007802 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007803 mWindow->consumeCaptureEvent(false);
7804 mWindow->assertNoEvents();
7805}
7806
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007807TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7808 requestAndVerifyPointerCapture(mWindow, true);
7809
7810 // The first window loses focus.
7811 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007812 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007813 mWindow->consumeCaptureEvent(false);
7814
7815 // Request Pointer Capture from the second window before the notification from InputReader
7816 // arrives.
7817 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007818 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007819
7820 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007821 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007822
7823 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007824 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007825
7826 mSecondWindow->consumeFocusEvent(true);
7827 mSecondWindow->consumeCaptureEvent(true);
7828}
7829
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007830TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7831 // App repeatedly enables and disables capture.
7832 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7833 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7834 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7835 mFakePolicy->assertSetPointerCaptureCalled(false);
7836 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7837 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7838
7839 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7840 // first request is now stale, this should do nothing.
7841 notifyPointerCaptureChanged(firstRequest);
7842 mWindow->assertNoEvents();
7843
7844 // InputReader notifies that the second request was enabled.
7845 notifyPointerCaptureChanged(secondRequest);
7846 mWindow->consumeCaptureEvent(true);
7847}
7848
Prabir Pradhan7092e262022-05-03 16:51:09 +00007849TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7850 requestAndVerifyPointerCapture(mWindow, true);
7851
7852 // App toggles pointer capture off and on.
7853 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7854 mFakePolicy->assertSetPointerCaptureCalled(false);
7855
7856 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7857 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7858
7859 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7860 // preceding "disable" request.
7861 notifyPointerCaptureChanged(enableRequest);
7862
7863 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7864 // any notifications.
7865 mWindow->assertNoEvents();
7866}
7867
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007868class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7869protected:
7870 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007871
7872 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7873 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7874
7875 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7876 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7877
7878 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7879 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7880 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7881 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7882 MAXIMUM_OBSCURING_OPACITY);
7883
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007884 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7885 static constexpr gui::Uid APP_B_UID{10002};
7886 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007887
7888 sp<FakeWindowHandle> mTouchWindow;
7889
7890 virtual void SetUp() override {
7891 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007892 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007893 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7894 }
7895
7896 virtual void TearDown() override {
7897 InputDispatcherTest::TearDown();
7898 mTouchWindow.clear();
7899 }
7900
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007901 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007902 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007903 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007904 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007905 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007906 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007907 return window;
7908 }
7909
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007910 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007911 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7912 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007913 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007914 // Generate an arbitrary PID based on the UID
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00007915 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007916 return window;
7917 }
7918
7919 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007920 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7921 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7922 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007923 }
7924};
7925
7926TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007927 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007928 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007930
7931 touch();
7932
7933 mTouchWindow->assertNoEvents();
7934}
7935
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007936TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007937 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7938 const sp<FakeWindowHandle>& w =
7939 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7940 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7941
7942 touch();
7943
7944 mTouchWindow->assertNoEvents();
7945}
7946
7947TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007948 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7949 const sp<FakeWindowHandle>& w =
7950 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7952
7953 touch();
7954
7955 w->assertNoEvents();
7956}
7957
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007958TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007959 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7960 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007961
7962 touch();
7963
7964 mTouchWindow->consumeAnyMotionDown();
7965}
7966
7967TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007968 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007970 w->setFrame(Rect(0, 0, 50, 50));
7971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007972
7973 touch({PointF{100, 100}});
7974
7975 mTouchWindow->consumeAnyMotionDown();
7976}
7977
7978TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007979 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007980 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7982
7983 touch();
7984
7985 mTouchWindow->consumeAnyMotionDown();
7986}
7987
7988TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7989 const sp<FakeWindowHandle>& w =
7990 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007992
7993 touch();
7994
7995 mTouchWindow->consumeAnyMotionDown();
7996}
7997
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007998TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7999 const sp<FakeWindowHandle>& w =
8000 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8002
8003 touch();
8004
8005 w->assertNoEvents();
8006}
8007
8008/**
8009 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8010 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8011 * window, the occluding window will still receive ACTION_OUTSIDE event.
8012 */
8013TEST_F(InputDispatcherUntrustedTouchesTest,
8014 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8015 const sp<FakeWindowHandle>& w =
8016 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008017 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8019
8020 touch();
8021
8022 w->consumeMotionOutside();
8023}
8024
8025TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8026 const sp<FakeWindowHandle>& w =
8027 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008028 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8030
8031 touch();
8032
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008033 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008034}
8035
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008036TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008037 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008038 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8039 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8041
8042 touch();
8043
8044 mTouchWindow->consumeAnyMotionDown();
8045}
8046
8047TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8048 const sp<FakeWindowHandle>& w =
8049 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8050 MAXIMUM_OBSCURING_OPACITY);
8051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008052
8053 touch();
8054
8055 mTouchWindow->consumeAnyMotionDown();
8056}
8057
8058TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008059 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008060 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8061 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8063
8064 touch();
8065
8066 mTouchWindow->assertNoEvents();
8067}
8068
8069TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8070 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8071 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008072 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8073 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008074 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008075 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8076 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8078
8079 touch();
8080
8081 mTouchWindow->assertNoEvents();
8082}
8083
8084TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8085 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8086 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008087 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8088 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008089 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008090 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8091 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8093
8094 touch();
8095
8096 mTouchWindow->consumeAnyMotionDown();
8097}
8098
8099TEST_F(InputDispatcherUntrustedTouchesTest,
8100 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8101 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008102 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8103 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008104 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008105 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8106 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8108
8109 touch();
8110
8111 mTouchWindow->consumeAnyMotionDown();
8112}
8113
8114TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8115 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008116 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8117 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008118 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008119 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8120 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008122
8123 touch();
8124
8125 mTouchWindow->assertNoEvents();
8126}
8127
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008128TEST_F(InputDispatcherUntrustedTouchesTest,
8129 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8130 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008131 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8132 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008133 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008134 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8135 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8137
8138 touch();
8139
8140 mTouchWindow->assertNoEvents();
8141}
8142
8143TEST_F(InputDispatcherUntrustedTouchesTest,
8144 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8145 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008146 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8147 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008148 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008149 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8150 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8152
8153 touch();
8154
8155 mTouchWindow->consumeAnyMotionDown();
8156}
8157
8158TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8159 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008160 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8161 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8163
8164 touch();
8165
8166 mTouchWindow->consumeAnyMotionDown();
8167}
8168
8169TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8170 const sp<FakeWindowHandle>& w =
8171 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8173
8174 touch();
8175
8176 mTouchWindow->consumeAnyMotionDown();
8177}
8178
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008179TEST_F(InputDispatcherUntrustedTouchesTest,
8180 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8181 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8182 const sp<FakeWindowHandle>& w =
8183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8184 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8185
8186 touch();
8187
8188 mTouchWindow->assertNoEvents();
8189}
8190
8191TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8192 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8193 const sp<FakeWindowHandle>& w =
8194 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8196
8197 touch();
8198
8199 mTouchWindow->consumeAnyMotionDown();
8200}
8201
8202TEST_F(InputDispatcherUntrustedTouchesTest,
8203 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8204 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8205 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008206 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8207 OPACITY_ABOVE_THRESHOLD);
8208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8209
8210 touch();
8211
8212 mTouchWindow->consumeAnyMotionDown();
8213}
8214
8215TEST_F(InputDispatcherUntrustedTouchesTest,
8216 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8217 const sp<FakeWindowHandle>& w1 =
8218 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8219 OPACITY_BELOW_THRESHOLD);
8220 const sp<FakeWindowHandle>& w2 =
8221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8222 OPACITY_BELOW_THRESHOLD);
8223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8224
8225 touch();
8226
8227 mTouchWindow->assertNoEvents();
8228}
8229
8230/**
8231 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8232 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8233 * (which alone would result in allowing touches) does not affect the blocking behavior.
8234 */
8235TEST_F(InputDispatcherUntrustedTouchesTest,
8236 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8237 const sp<FakeWindowHandle>& wB =
8238 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8239 OPACITY_BELOW_THRESHOLD);
8240 const sp<FakeWindowHandle>& wC =
8241 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8242 OPACITY_BELOW_THRESHOLD);
8243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8244
8245 touch();
8246
8247 mTouchWindow->assertNoEvents();
8248}
8249
8250/**
8251 * This test is testing that a window from a different UID but with same application token doesn't
8252 * block the touch. Apps can share the application token for close UI collaboration for example.
8253 */
8254TEST_F(InputDispatcherUntrustedTouchesTest,
8255 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8256 const sp<FakeWindowHandle>& w =
8257 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8258 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8260
8261 touch();
8262
8263 mTouchWindow->consumeAnyMotionDown();
8264}
8265
arthurhungb89ccb02020-12-30 16:19:01 +08008266class InputDispatcherDragTests : public InputDispatcherTest {
8267protected:
8268 std::shared_ptr<FakeApplicationHandle> mApp;
8269 sp<FakeWindowHandle> mWindow;
8270 sp<FakeWindowHandle> mSecondWindow;
8271 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008272 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008273 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8274 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008275
8276 void SetUp() override {
8277 InputDispatcherTest::SetUp();
8278 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008279 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008280 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008281
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008282 mSecondWindow =
8283 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008284 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008285
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008286 mSpyWindow =
8287 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008288 mSpyWindow->setSpy(true);
8289 mSpyWindow->setTrustedOverlay(true);
8290 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8291
arthurhungb89ccb02020-12-30 16:19:01 +08008292 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008294 }
8295
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008296 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8297 switch (fromSource) {
8298 case AINPUT_SOURCE_TOUCHSCREEN:
8299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8300 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8301 ADISPLAY_ID_DEFAULT, {50, 50}))
8302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8303 break;
8304 case AINPUT_SOURCE_STYLUS:
8305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8306 injectMotionEvent(
8307 mDispatcher,
8308 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8309 AINPUT_SOURCE_STYLUS)
8310 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008311 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008312 .x(50)
8313 .y(50))
8314 .build()));
8315 break;
8316 case AINPUT_SOURCE_MOUSE:
8317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8318 injectMotionEvent(
8319 mDispatcher,
8320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8321 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8322 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008323 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008324 .x(50)
8325 .y(50))
8326 .build()));
8327 break;
8328 default:
8329 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8330 }
arthurhungb89ccb02020-12-30 16:19:01 +08008331
8332 // Window should receive motion event.
8333 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008334 // Spy window should also receive motion event
8335 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008336 }
8337
8338 // Start performing drag, we will create a drag window and transfer touch to it.
8339 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8340 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008341 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008342 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008343 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008344 }
arthurhungb89ccb02020-12-30 16:19:01 +08008345
8346 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008347 mDragWindow =
8348 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008349 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008350 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008351 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008352
8353 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008354 bool transferred =
8355 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008356 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008357 if (transferred) {
8358 mWindow->consumeMotionCancel();
8359 mDragWindow->consumeMotionDown();
8360 }
8361 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008362 }
8363};
8364
8365TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008366 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008367
8368 // Move on window.
8369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8370 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8371 ADISPLAY_ID_DEFAULT, {50, 50}))
8372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8373 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8374 mWindow->consumeDragEvent(false, 50, 50);
8375 mSecondWindow->assertNoEvents();
8376
8377 // Move to another window.
8378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8379 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8380 ADISPLAY_ID_DEFAULT, {150, 50}))
8381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8382 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8383 mWindow->consumeDragEvent(true, 150, 50);
8384 mSecondWindow->consumeDragEvent(false, 50, 50);
8385
8386 // Move back to original window.
8387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8388 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8389 ADISPLAY_ID_DEFAULT, {50, 50}))
8390 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8391 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8392 mWindow->consumeDragEvent(false, 50, 50);
8393 mSecondWindow->consumeDragEvent(true, -50, 50);
8394
8395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8396 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8398 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8399 mWindow->assertNoEvents();
8400 mSecondWindow->assertNoEvents();
8401}
8402
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008403TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008404 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008405
8406 // No cancel event after drag start
8407 mSpyWindow->assertNoEvents();
8408
8409 const MotionEvent secondFingerDownEvent =
8410 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
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(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +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";
8419
8420 // Receives cancel for first pointer after next pointer down
8421 mSpyWindow->consumeMotionCancel();
8422 mSpyWindow->consumeMotionDown();
8423
8424 mSpyWindow->assertNoEvents();
8425}
8426
arthurhungf452d0b2021-01-06 00:19:52 +08008427TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008428 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008429
8430 // Move on window.
8431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8432 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8433 ADISPLAY_ID_DEFAULT, {50, 50}))
8434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8435 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8436 mWindow->consumeDragEvent(false, 50, 50);
8437 mSecondWindow->assertNoEvents();
8438
8439 // Move to another window.
8440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8441 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8442 ADISPLAY_ID_DEFAULT, {150, 50}))
8443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8444 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8445 mWindow->consumeDragEvent(true, 150, 50);
8446 mSecondWindow->consumeDragEvent(false, 50, 50);
8447
8448 // drop to another window.
8449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8450 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8451 {150, 50}))
8452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8453 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8454 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8455 mWindow->assertNoEvents();
8456 mSecondWindow->assertNoEvents();
8457}
8458
arthurhung6d4bed92021-03-17 11:59:33 +08008459TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008460 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008461
8462 // Move on window and keep button pressed.
8463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8464 injectMotionEvent(mDispatcher,
8465 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8466 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008467 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008468 .build()))
8469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8471 mWindow->consumeDragEvent(false, 50, 50);
8472 mSecondWindow->assertNoEvents();
8473
8474 // Move to another window and release button, expect to drop item.
8475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8476 injectMotionEvent(mDispatcher,
8477 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8478 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008479 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008480 .build()))
8481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8482 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8483 mWindow->assertNoEvents();
8484 mSecondWindow->assertNoEvents();
8485 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8486
8487 // nothing to the window.
8488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8489 injectMotionEvent(mDispatcher,
8490 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8491 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008492 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008493 .build()))
8494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8495 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8496 mWindow->assertNoEvents();
8497 mSecondWindow->assertNoEvents();
8498}
8499
Arthur Hung54745652022-04-20 07:17:41 +00008500TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008501 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008502
8503 // Set second window invisible.
8504 mSecondWindow->setVisible(false);
8505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8506
8507 // Move on window.
8508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8509 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8510 ADISPLAY_ID_DEFAULT, {50, 50}))
8511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8512 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8513 mWindow->consumeDragEvent(false, 50, 50);
8514 mSecondWindow->assertNoEvents();
8515
8516 // Move to another window.
8517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8518 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8519 ADISPLAY_ID_DEFAULT, {150, 50}))
8520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8521 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8522 mWindow->consumeDragEvent(true, 150, 50);
8523 mSecondWindow->assertNoEvents();
8524
8525 // drop to another window.
8526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8527 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8528 {150, 50}))
8529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8530 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8531 mFakePolicy->assertDropTargetEquals(nullptr);
8532 mWindow->assertNoEvents();
8533 mSecondWindow->assertNoEvents();
8534}
8535
Arthur Hung54745652022-04-20 07:17:41 +00008536TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008537 // Ensure window could track pointerIds if it didn't support split touch.
8538 mWindow->setPreventSplitting(true);
8539
Arthur Hung54745652022-04-20 07:17:41 +00008540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8541 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8542 {50, 50}))
8543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8544 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8545
8546 const MotionEvent secondFingerDownEvent =
8547 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8548 .displayId(ADISPLAY_ID_DEFAULT)
8549 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008550 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8551 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008552 .build();
8553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8554 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8555 InputEventInjectionSync::WAIT_FOR_RESULT))
8556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008557 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008558
8559 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008560 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008561}
8562
8563TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8564 // First down on second window.
8565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8567 {150, 50}))
8568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8569
8570 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8571
8572 // Second down on first window.
8573 const MotionEvent secondFingerDownEvent =
8574 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8575 .displayId(ADISPLAY_ID_DEFAULT)
8576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008579 .build();
8580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8581 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8582 InputEventInjectionSync::WAIT_FOR_RESULT))
8583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8584 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8585
8586 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008587 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008588
8589 // Move on window.
8590 const MotionEvent secondFingerMoveEvent =
8591 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8592 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008593 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8594 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008595 .build();
8596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8597 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8598 InputEventInjectionSync::WAIT_FOR_RESULT));
8599 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8600 mWindow->consumeDragEvent(false, 50, 50);
8601 mSecondWindow->consumeMotionMove();
8602
8603 // Release the drag pointer should perform drop.
8604 const MotionEvent secondFingerUpEvent =
8605 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8606 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008607 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8608 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008609 .build();
8610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8611 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8612 InputEventInjectionSync::WAIT_FOR_RESULT));
8613 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8614 mFakePolicy->assertDropTargetEquals(mWindow->getToken());
8615 mWindow->assertNoEvents();
8616 mSecondWindow->consumeMotionMove();
8617}
8618
Arthur Hung3915c1f2022-05-31 07:17:17 +00008619TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008620 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008621
8622 // Update window of second display.
8623 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008624 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008625 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8626
8627 // Let second display has a touch state.
8628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8629 injectMotionEvent(mDispatcher,
8630 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8631 AINPUT_SOURCE_TOUCHSCREEN)
8632 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008633 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008634 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008635 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008636 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008637 // Update window again.
8638 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8639
8640 // Move on window.
8641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8642 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8643 ADISPLAY_ID_DEFAULT, {50, 50}))
8644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8645 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8646 mWindow->consumeDragEvent(false, 50, 50);
8647 mSecondWindow->assertNoEvents();
8648
8649 // Move to another window.
8650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8651 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8652 ADISPLAY_ID_DEFAULT, {150, 50}))
8653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8654 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8655 mWindow->consumeDragEvent(true, 150, 50);
8656 mSecondWindow->consumeDragEvent(false, 50, 50);
8657
8658 // drop to another window.
8659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8660 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8661 {150, 50}))
8662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8663 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8664 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8665 mWindow->assertNoEvents();
8666 mSecondWindow->assertNoEvents();
8667}
8668
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008669TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8670 startDrag(true, AINPUT_SOURCE_MOUSE);
8671 // Move on window.
8672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8673 injectMotionEvent(mDispatcher,
8674 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8675 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8676 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008677 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008678 .x(50)
8679 .y(50))
8680 .build()))
8681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8682 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8683 mWindow->consumeDragEvent(false, 50, 50);
8684 mSecondWindow->assertNoEvents();
8685
8686 // Move to another window.
8687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8688 injectMotionEvent(mDispatcher,
8689 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8690 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8691 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008692 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008693 .x(150)
8694 .y(50))
8695 .build()))
8696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8697 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8698 mWindow->consumeDragEvent(true, 150, 50);
8699 mSecondWindow->consumeDragEvent(false, 50, 50);
8700
8701 // drop to another window.
8702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8703 injectMotionEvent(mDispatcher,
8704 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8705 .buttonState(0)
8706 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008707 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008708 .x(150)
8709 .y(50))
8710 .build()))
8711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8712 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8713 mFakePolicy->assertDropTargetEquals(mSecondWindow->getToken());
8714 mWindow->assertNoEvents();
8715 mSecondWindow->assertNoEvents();
8716}
8717
Vishnu Nair062a8672021-09-03 16:07:44 -07008718class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8719
8720TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8723 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008724 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008725 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8726 window->setFocusable(true);
8727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8728 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008729 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008730
8731 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008732 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008733 window->assertNoEvents();
8734
Prabir Pradhan678438e2023-04-13 19:32:51 +00008735 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8736 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008737 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8738 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008739 window->assertNoEvents();
8740
8741 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008742 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008743 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8744
Prabir Pradhan678438e2023-04-13 19:32:51 +00008745 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008746 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8747
Prabir Pradhan678438e2023-04-13 19:32:51 +00008748 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8749 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008750 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8751 window->assertNoEvents();
8752}
8753
8754TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8755 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8756 std::make_shared<FakeApplicationHandle>();
8757 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008758 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8759 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008760 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008761 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008762 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008763 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008764 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8765 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008766 window->setDropInputIfObscured(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008767 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008768 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8769 window->setFocusable(true);
8770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8771 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008772 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008773
8774 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008775 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008776 window->assertNoEvents();
8777
Prabir Pradhan678438e2023-04-13 19:32:51 +00008778 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8779 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008780 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8781 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008782 window->assertNoEvents();
8783
8784 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008785 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008786 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8787
Prabir Pradhan678438e2023-04-13 19:32:51 +00008788 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008789 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8790
Prabir Pradhan678438e2023-04-13 19:32:51 +00008791 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8792 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008793 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8794 window->assertNoEvents();
8795}
8796
8797TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8798 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8799 std::make_shared<FakeApplicationHandle>();
8800 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008801 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8802 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008803 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008804 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008805 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008807 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8808 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008809 window->setDropInputIfObscured(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008810 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008811 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8812 window->setFocusable(true);
8813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8814 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008815 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008816
8817 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008818 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008819 window->assertNoEvents();
8820
Prabir Pradhan678438e2023-04-13 19:32:51 +00008821 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8822 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8824 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008825 window->assertNoEvents();
8826
8827 // When the window is no longer obscured because it went on top, it should get input
8828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8829
Prabir Pradhan678438e2023-04-13 19:32:51 +00008830 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008831 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8832
Prabir Pradhan678438e2023-04-13 19:32:51 +00008833 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8834 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008835 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8836 window->assertNoEvents();
8837}
8838
Antonio Kantekf16f2832021-09-28 04:39:20 +00008839class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8840protected:
8841 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008842 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008843 sp<FakeWindowHandle> mWindow;
8844 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008845 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008846
8847 void SetUp() override {
8848 InputDispatcherTest::SetUp();
8849
8850 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008851 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008852 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008853 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008854 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008855 mSecondWindow =
8856 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008857 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008858 mThirdWindow =
8859 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8860 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8861 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008862
8863 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008864 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8865 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8866 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008867 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008868
Antonio Kantek15beb512022-06-13 22:35:41 +00008869 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008870 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008871 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008872 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8873 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008874 mThirdWindow->assertNoEvents();
8875 }
8876
8877 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8878 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008879 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008880 SECOND_DISPLAY_ID)) {
8881 mWindow->assertNoEvents();
8882 mSecondWindow->assertNoEvents();
8883 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008884 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008885 }
8886
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008887 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008888 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008889 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8890 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008891 mWindow->consumeTouchModeEvent(inTouchMode);
8892 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008893 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008894 }
8895};
8896
Antonio Kantek26defcf2022-02-08 01:12:27 +00008897TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008898 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008899 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8900 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008901 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008902}
8903
Antonio Kantek26defcf2022-02-08 01:12:27 +00008904TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8905 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008906 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008907 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008908 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008909 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008910 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008911 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008912 mWindow->assertNoEvents();
8913 mSecondWindow->assertNoEvents();
8914}
8915
8916TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8917 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008918 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008919 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008920 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008921 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008922 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008923}
8924
Antonio Kantekf16f2832021-09-28 04:39:20 +00008925TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008926 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008927 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8928 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008929 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008930 mWindow->assertNoEvents();
8931 mSecondWindow->assertNoEvents();
8932}
8933
Antonio Kantek15beb512022-06-13 22:35:41 +00008934TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8935 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8936 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8937 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008938 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008939 mWindow->assertNoEvents();
8940 mSecondWindow->assertNoEvents();
8941 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8942}
8943
Antonio Kantek48710e42022-03-24 14:19:30 -07008944TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8945 // Interact with the window first.
8946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8947 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8948 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8949
8950 // Then remove focus.
8951 mWindow->setFocusable(false);
8952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8953
8954 // Assert that caller can switch touch mode by owning one of the last interacted window.
8955 const WindowInfo& windowInfo = *mWindow->getInfo();
8956 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8957 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008958 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008959}
8960
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008961class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8962public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008963 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008964 std::shared_ptr<FakeApplicationHandle> application =
8965 std::make_shared<FakeApplicationHandle>();
8966 std::string name = "Fake Spy ";
8967 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008968 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8969 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008970 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008971 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008972 return spy;
8973 }
8974
8975 sp<FakeWindowHandle> createForeground() {
8976 std::shared_ptr<FakeApplicationHandle> application =
8977 std::make_shared<FakeApplicationHandle>();
8978 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008979 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8980 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008981 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008982 return window;
8983 }
8984
8985private:
8986 int mSpyCount{0};
8987};
8988
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008989using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008990/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008991 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8992 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008993TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8994 ScopedSilentDeath _silentDeath;
8995
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008996 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008997 spy->setTrustedOverlay(false);
8998 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8999 ".* not a trusted overlay");
9000}
9001
9002/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009003 * Input injection into a display with a spy window but no foreground windows should succeed.
9004 */
9005TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009006 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009007 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9008
9009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9010 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9011 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9012 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9013}
9014
9015/**
9016 * Verify the order in which different input windows receive events. The touched foreground window
9017 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9018 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9019 * receive events before ones belows it.
9020 *
9021 * Here, we set up a scenario with four windows in the following Z order from the top:
9022 * spy1, spy2, window, spy3.
9023 * We then inject an event and verify that the foreground "window" receives it first, followed by
9024 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9025 * window.
9026 */
9027TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9028 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009029 auto spy1 = createSpy();
9030 auto spy2 = createSpy();
9031 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009032 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9033 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9034 const size_t numChannels = channels.size();
9035
Michael Wright8e9a8562022-02-09 13:44:29 +00009036 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009037 if (!epollFd.ok()) {
9038 FAIL() << "Failed to create epoll fd";
9039 }
9040
9041 for (size_t i = 0; i < numChannels; i++) {
9042 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9043 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9044 FAIL() << "Failed to add fd to epoll";
9045 }
9046 }
9047
9048 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9049 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9051
9052 std::vector<size_t> eventOrder;
9053 std::vector<struct epoll_event> events(numChannels);
9054 for (;;) {
9055 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9056 (100ms).count());
9057 if (nFds < 0) {
9058 FAIL() << "Failed to call epoll_wait";
9059 }
9060 if (nFds == 0) {
9061 break; // epoll_wait timed out
9062 }
9063 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009064 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009065 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009066 channels[i]->consumeMotionDown();
9067 }
9068 }
9069
9070 // Verify the order in which the events were received.
9071 EXPECT_EQ(3u, eventOrder.size());
9072 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9073 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9074 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9075}
9076
9077/**
9078 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9079 */
9080TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9081 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009082 auto spy = createSpy();
9083 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009084 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9085
9086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9087 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9089 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9090 spy->assertNoEvents();
9091}
9092
9093/**
9094 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9095 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9096 * to the window.
9097 */
9098TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9099 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009100 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009101 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9102 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9103
9104 // Inject an event outside the spy window's touchable region.
9105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9106 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9107 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9108 window->consumeMotionDown();
9109 spy->assertNoEvents();
9110 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9111 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9113 window->consumeMotionUp();
9114 spy->assertNoEvents();
9115
9116 // Inject an event inside the spy window's touchable region.
9117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9118 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9119 {5, 10}))
9120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9121 window->consumeMotionDown();
9122 spy->consumeMotionDown();
9123}
9124
9125/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009126 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009127 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009128 */
9129TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9130 auto window = createForeground();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009131 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009132 auto spy = createSpy();
9133 spy->setWatchOutsideTouch(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009134 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009135 spy->setFrame(Rect{0, 0, 20, 20});
9136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9137
9138 // Inject an event outside the spy window's frame and touchable region.
9139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009140 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9141 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009142 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9143 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009144 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009145}
9146
9147/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009148 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9149 * pointers that are down within its bounds.
9150 */
9151TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9152 auto windowLeft = createForeground();
9153 windowLeft->setFrame({0, 0, 100, 200});
9154 auto windowRight = createForeground();
9155 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009156 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009157 spy->setFrame({0, 0, 200, 200});
9158 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9159
9160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9161 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9162 {50, 50}))
9163 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9164 windowLeft->consumeMotionDown();
9165 spy->consumeMotionDown();
9166
9167 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009168 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009169 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009170 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9171 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009172 .build();
9173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9174 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9175 InputEventInjectionSync::WAIT_FOR_RESULT))
9176 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9177 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009178 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009179}
9180
9181/**
9182 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9183 * the spy should receive the second pointer with ACTION_DOWN.
9184 */
9185TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9186 auto window = createForeground();
9187 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009188 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009189 spyRight->setFrame({100, 0, 200, 200});
9190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9191
9192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9193 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9194 {50, 50}))
9195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9196 window->consumeMotionDown();
9197 spyRight->assertNoEvents();
9198
9199 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009200 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009201 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009202 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9203 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009204 .build();
9205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9206 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9207 InputEventInjectionSync::WAIT_FOR_RESULT))
9208 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009209 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009210 spyRight->consumeMotionDown();
9211}
9212
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009213/**
9214 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9215 * windows should be allowed to control split touch.
9216 */
9217TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009218 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009219 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009220 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009221 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009222
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009223 auto window = createForeground();
9224 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009225
9226 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9227
9228 // First finger down, no window touched.
9229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9230 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9231 {100, 200}))
9232 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9233 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9234 window->assertNoEvents();
9235
9236 // Second finger down on window, the window should receive touch down.
9237 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009238 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009239 .displayId(ADISPLAY_ID_DEFAULT)
9240 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009241 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9242 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009243 .build();
9244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9245 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9246 InputEventInjectionSync::WAIT_FOR_RESULT))
9247 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9248
9249 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009250 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009251}
9252
9253/**
9254 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9255 * do not receive key events.
9256 */
9257TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009258 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009259 spy->setFocusable(false);
9260
9261 auto window = createForeground();
9262 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9263 setFocusedWindow(window);
9264 window->consumeFocusEvent(true);
9265
9266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9267 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9268 window->consumeKeyDown(ADISPLAY_ID_NONE);
9269
9270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9271 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9272 window->consumeKeyUp(ADISPLAY_ID_NONE);
9273
9274 spy->assertNoEvents();
9275}
9276
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009277using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9278
9279/**
9280 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9281 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9282 */
9283TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9284 auto window = createForeground();
9285 auto spy1 = createSpy();
9286 auto spy2 = createSpy();
9287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9288
9289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9290 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9292 window->consumeMotionDown();
9293 spy1->consumeMotionDown();
9294 spy2->consumeMotionDown();
9295
9296 // Pilfer pointers from the second spy window.
9297 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9298 spy2->assertNoEvents();
9299 spy1->consumeMotionCancel();
9300 window->consumeMotionCancel();
9301
9302 // The rest of the gesture should only be sent to the second spy window.
9303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9304 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9305 ADISPLAY_ID_DEFAULT))
9306 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9307 spy2->consumeMotionMove();
9308 spy1->assertNoEvents();
9309 window->assertNoEvents();
9310}
9311
9312/**
9313 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9314 * in the middle of the gesture.
9315 */
9316TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9317 auto window = createForeground();
9318 auto spy = createSpy();
9319 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9320
9321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9322 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9324 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9325 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9326
9327 window->releaseChannel();
9328
9329 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9330
9331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9332 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9334 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9335}
9336
9337/**
9338 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9339 * the spy, but not to any other windows.
9340 */
9341TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9342 auto spy = createSpy();
9343 auto window = createForeground();
9344
9345 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9346
9347 // First finger down on the window and the spy.
9348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9349 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9350 {100, 200}))
9351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9352 spy->consumeMotionDown();
9353 window->consumeMotionDown();
9354
9355 // Spy window pilfers the pointers.
9356 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9357 window->consumeMotionCancel();
9358
9359 // Second finger down on the window and spy, but the window should not receive the pointer down.
9360 const MotionEvent secondFingerDownEvent =
9361 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9362 .displayId(ADISPLAY_ID_DEFAULT)
9363 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009364 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9365 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009366 .build();
9367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9368 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9369 InputEventInjectionSync::WAIT_FOR_RESULT))
9370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9371
Harry Cutts33476232023-01-30 19:57:29 +00009372 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009373
9374 // Third finger goes down outside all windows, so injection should fail.
9375 const MotionEvent thirdFingerDownEvent =
9376 MotionEventBuilder(POINTER_2_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(100).y(200))
9380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9381 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009382 .build();
9383 ASSERT_EQ(InputEventInjectionResult::FAILED,
9384 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9385 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009386 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009387
9388 spy->assertNoEvents();
9389 window->assertNoEvents();
9390}
9391
9392/**
9393 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9394 */
9395TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9396 auto spy = createSpy();
9397 spy->setFrame(Rect(0, 0, 100, 100));
9398 auto window = createForeground();
9399 window->setFrame(Rect(0, 0, 200, 200));
9400
9401 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9402
9403 // First finger down on the window only
9404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9405 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9406 {150, 150}))
9407 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9408 window->consumeMotionDown();
9409
9410 // Second finger down on the spy and window
9411 const MotionEvent secondFingerDownEvent =
9412 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9413 .displayId(ADISPLAY_ID_DEFAULT)
9414 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009415 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9416 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009417 .build();
9418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9419 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9420 InputEventInjectionSync::WAIT_FOR_RESULT))
9421 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9422 spy->consumeMotionDown();
9423 window->consumeMotionPointerDown(1);
9424
9425 // Third finger down on the spy and window
9426 const MotionEvent thirdFingerDownEvent =
9427 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9428 .displayId(ADISPLAY_ID_DEFAULT)
9429 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009430 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9431 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9432 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009433 .build();
9434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9435 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9436 InputEventInjectionSync::WAIT_FOR_RESULT))
9437 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9438 spy->consumeMotionPointerDown(1);
9439 window->consumeMotionPointerDown(2);
9440
9441 // Spy window pilfers the pointers.
9442 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9443 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9444 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9445
9446 spy->assertNoEvents();
9447 window->assertNoEvents();
9448}
9449
9450/**
9451 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9452 * other windows should be canceled. If this results in the cancellation of all pointers for some
9453 * window, then that window should receive ACTION_CANCEL.
9454 */
9455TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9456 auto spy = createSpy();
9457 spy->setFrame(Rect(0, 0, 100, 100));
9458 auto window = createForeground();
9459 window->setFrame(Rect(0, 0, 200, 200));
9460
9461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9462
9463 // First finger down on both spy and window
9464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9465 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9466 {10, 10}))
9467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9468 window->consumeMotionDown();
9469 spy->consumeMotionDown();
9470
9471 // Second finger down on the spy and window
9472 const MotionEvent secondFingerDownEvent =
9473 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9474 .displayId(ADISPLAY_ID_DEFAULT)
9475 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009476 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9477 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009478 .build();
9479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9480 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9481 InputEventInjectionSync::WAIT_FOR_RESULT))
9482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9483 spy->consumeMotionPointerDown(1);
9484 window->consumeMotionPointerDown(1);
9485
9486 // Spy window pilfers the pointers.
9487 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9488 window->consumeMotionCancel();
9489
9490 spy->assertNoEvents();
9491 window->assertNoEvents();
9492}
9493
9494/**
9495 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9496 * be sent to other windows
9497 */
9498TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9499 auto spy = createSpy();
9500 spy->setFrame(Rect(0, 0, 100, 100));
9501 auto window = createForeground();
9502 window->setFrame(Rect(0, 0, 200, 200));
9503
9504 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9505
9506 // First finger down on both window and spy
9507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9508 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9509 {10, 10}))
9510 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9511 window->consumeMotionDown();
9512 spy->consumeMotionDown();
9513
9514 // Spy window pilfers the pointers.
9515 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9516 window->consumeMotionCancel();
9517
9518 // Second finger down on the window only
9519 const MotionEvent secondFingerDownEvent =
9520 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9521 .displayId(ADISPLAY_ID_DEFAULT)
9522 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009523 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9524 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009525 .build();
9526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9527 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9528 InputEventInjectionSync::WAIT_FOR_RESULT))
9529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9530 window->consumeMotionDown();
9531 window->assertNoEvents();
9532
9533 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9534 spy->consumeMotionMove();
9535 spy->assertNoEvents();
9536}
9537
Prabir Pradhand65552b2021-10-07 11:23:50 -07009538class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9539public:
9540 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9541 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9542 std::make_shared<FakeApplicationHandle>();
9543 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009544 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9545 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009546 overlay->setFocusable(false);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009547 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009548 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009549 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009550 overlay->setTrustedOverlay(true);
9551
9552 std::shared_ptr<FakeApplicationHandle> application =
9553 std::make_shared<FakeApplicationHandle>();
9554 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009555 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9556 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009557 window->setFocusable(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009558 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009559
9560 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9562 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009563 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009564 return {std::move(overlay), std::move(window)};
9565 }
9566
9567 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009568 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009569 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009570 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009571 }
9572
9573 void sendStylusEvent(int32_t action) {
9574 NotifyMotionArgs motionArgs =
9575 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9576 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009577 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009578 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009579 }
9580};
9581
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009582using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9583
9584TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
9585 ScopedSilentDeath _silentDeath;
9586
Prabir Pradhand65552b2021-10-07 11:23:50 -07009587 auto [overlay, window] = setupStylusOverlayScenario();
9588 overlay->setTrustedOverlay(false);
9589 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9590 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9591 ".* not a trusted overlay");
9592}
9593
9594TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9595 auto [overlay, window] = setupStylusOverlayScenario();
9596 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9597
9598 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9599 overlay->consumeMotionDown();
9600 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9601 overlay->consumeMotionUp();
9602
9603 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9604 window->consumeMotionDown();
9605 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9606 window->consumeMotionUp();
9607
9608 overlay->assertNoEvents();
9609 window->assertNoEvents();
9610}
9611
9612TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9613 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009614 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009615 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9616
9617 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9618 overlay->consumeMotionDown();
9619 window->consumeMotionDown();
9620 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9621 overlay->consumeMotionUp();
9622 window->consumeMotionUp();
9623
9624 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9625 window->consumeMotionDown();
9626 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9627 window->consumeMotionUp();
9628
9629 overlay->assertNoEvents();
9630 window->assertNoEvents();
9631}
9632
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009633/**
9634 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9635 * The scenario is as follows:
9636 * - The stylus interceptor overlay is configured as a spy window.
9637 * - The stylus interceptor spy receives the start of a new stylus gesture.
9638 * - It pilfers pointers and then configures itself to no longer be a spy.
9639 * - The stylus interceptor continues to receive the rest of the gesture.
9640 */
9641TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9642 auto [overlay, window] = setupStylusOverlayScenario();
9643 overlay->setSpy(true);
9644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9645
9646 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9647 overlay->consumeMotionDown();
9648 window->consumeMotionDown();
9649
9650 // The interceptor pilfers the pointers.
9651 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9652 window->consumeMotionCancel();
9653
9654 // The interceptor configures itself so that it is no longer a spy.
9655 overlay->setSpy(false);
9656 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9657
9658 // It continues to receive the rest of the stylus gesture.
9659 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9660 overlay->consumeMotionMove();
9661 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9662 overlay->consumeMotionUp();
9663
9664 window->assertNoEvents();
9665}
9666
Prabir Pradhan5735a322022-04-11 17:23:34 +00009667struct User {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009668 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009669 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009670 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9671 std::unique_ptr<InputDispatcher>& mDispatcher;
9672
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009673 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009674 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9675
9676 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9677 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9678 ADISPLAY_ID_DEFAULT, {100, 200},
9679 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9680 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9681 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9682 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9683 }
9684
9685 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009686 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009687 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009688 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009689 mPolicyFlags);
9690 }
9691
9692 sp<FakeWindowHandle> createWindow() const {
9693 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9694 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009695 sp<FakeWindowHandle> window =
9696 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9697 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009698 window->setOwnerInfo(mPid, mUid);
9699 return window;
9700 }
9701};
9702
9703using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9704
9705TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009706 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009707 auto window = owner.createWindow();
9708 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9709
9710 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9711 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9712 window->consumeMotionDown();
9713
9714 setFocusedWindow(window);
9715 window->consumeFocusEvent(true);
9716
9717 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9718 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9719 window->consumeKeyDown(ADISPLAY_ID_NONE);
9720}
9721
9722TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009723 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009724 auto window = owner.createWindow();
9725 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9726
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009727 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009728 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9729 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9730
9731 setFocusedWindow(window);
9732 window->consumeFocusEvent(true);
9733
9734 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9735 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9736 window->assertNoEvents();
9737}
9738
9739TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009740 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009741 auto window = owner.createWindow();
9742 auto spy = owner.createWindow();
9743 spy->setSpy(true);
9744 spy->setTrustedOverlay(true);
9745 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9746
9747 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9748 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9749 spy->consumeMotionDown();
9750 window->consumeMotionDown();
9751}
9752
9753TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009754 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009755 auto window = owner.createWindow();
9756
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009757 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009758 auto randosSpy = rando.createWindow();
9759 randosSpy->setSpy(true);
9760 randosSpy->setTrustedOverlay(true);
9761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9762
9763 // The event is targeted at owner's window, so injection should succeed, but the spy should
9764 // not receive the event.
9765 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9766 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9767 randosSpy->assertNoEvents();
9768 window->consumeMotionDown();
9769}
9770
9771TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009772 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009773 auto window = owner.createWindow();
9774
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009775 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009776 auto randosSpy = rando.createWindow();
9777 randosSpy->setSpy(true);
9778 randosSpy->setTrustedOverlay(true);
9779 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9780
9781 // A user that has injection permission can inject into any window.
9782 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9783 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9784 ADISPLAY_ID_DEFAULT));
9785 randosSpy->consumeMotionDown();
9786 window->consumeMotionDown();
9787
9788 setFocusedWindow(randosSpy);
9789 randosSpy->consumeFocusEvent(true);
9790
9791 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9792 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9793 window->assertNoEvents();
9794}
9795
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009796TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009797 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009798 auto window = owner.createWindow();
9799
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009800 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009801 auto randosWindow = rando.createWindow();
9802 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9803 randosWindow->setWatchOutsideTouch(true);
9804 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9805
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009806 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009807 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9808 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9809 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009810 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009811}
9812
Garfield Tane84e6f92019-08-29 17:28:41 -07009813} // namespace android::inputdispatcher