blob: 6ab263d829538ecd28ff96e5d38bf5f2a4f909a6 [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
Cody Heiner166a5af2023-07-07 12:25:00 -070020#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir 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
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700387 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
388 const sp<IBinder>& targetToken) {
389 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800390 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800391 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800392 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800393 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800394 }
395
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800396 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
397 std::unique_lock lock(mLock);
398 base::ScopedLockAssertion assumeLocked(mLock);
399 std::optional<sp<IBinder>> receivedToken =
400 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
401 mNotifyInputChannelBroken);
402 ASSERT_TRUE(receivedToken.has_value());
403 ASSERT_EQ(token, *receivedToken);
404 }
405
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800406 /**
407 * Set policy timeout. A value of zero means next key will not be intercepted.
408 */
409 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
410 mInterceptKeyTimeout = timeout;
411 }
412
Josep del Riob3981622023-04-18 15:49:45 +0000413 void assertUserActivityPoked() {
414 std::scoped_lock lock(mLock);
415 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
416 }
417
418 void assertUserActivityNotPoked() {
419 std::scoped_lock lock(mLock);
420 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
421 }
422
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000423 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000424 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
425 }
426
427 void assertNotifyDeviceInteractionWasNotCalled() {
428 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
429 }
430
Michael Wrightd02c5b62014-02-10 15:10:22 -0800431private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700432 std::mutex mLock;
433 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
434 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
435 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
436 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800437
Prabir Pradhan99987712020-11-10 18:43:05 -0800438 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000439
440 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800441
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700442 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700443 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800444 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
445 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700446 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800447 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
448 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700449
arthurhungf452d0b2021-01-06 00:19:52 +0800450 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800451 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000452 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800453
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800454 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
455
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000456 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000457
Prabir Pradhanedd96402022-02-15 01:46:16 -0800458 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
459 // for a specific container to become non-empty. When the container is non-empty, return the
460 // first entry from the container and erase it.
461 template <class T>
462 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
463 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
464 // If there is an ANR, Dispatcher won't be idle because there are still events
465 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
466 // before checking if ANR was called.
467 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
468 // to provide it some time to act. 100ms seems reasonable.
469 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
470 const std::chrono::time_point start = std::chrono::steady_clock::now();
471 std::optional<T> token =
472 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
473 if (!token.has_value()) {
474 ADD_FAILURE() << "Did not receive the ANR callback";
475 return {};
476 }
477
478 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
479 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
480 // the dispatcher started counting before this function was called
481 if (std::chrono::abs(timeout - waited) > 100ms) {
482 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
483 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
484 << "ms, but waited "
485 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
486 << "ms instead";
487 }
488 return *token;
489 }
490
491 template <class T>
492 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
493 std::queue<T>& storage,
494 std::unique_lock<std::mutex>& lock,
495 std::condition_variable& condition)
496 REQUIRES(mLock) {
497 condition.wait_for(lock, timeout,
498 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
499 if (storage.empty()) {
500 ADD_FAILURE() << "Did not receive the expected callback";
501 return std::nullopt;
502 }
503 T item = storage.front();
504 storage.pop();
505 return std::make_optional(item);
506 }
507
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600508 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700509 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800510 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511 }
512
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000513 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800514 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700515 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800516 ASSERT_TRUE(pid.has_value());
517 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700518 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500519 }
520
Prabir Pradhanedd96402022-02-15 01:46:16 -0800521 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhane59c6dc2023-06-13 19:53:03 +0000522 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500523 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800524 ASSERT_TRUE(pid.has_value());
525 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500526 mNotifyAnr.notify_all();
527 }
528
529 void notifyNoFocusedWindowAnr(
530 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
531 std::scoped_lock lock(mLock);
532 mAnrApplications.push(applicationHandle);
533 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534 }
535
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800536 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
537 std::scoped_lock lock(mLock);
538 mBrokenInputChannels.push(connectionToken);
539 mNotifyInputChannelBroken.notify_all();
540 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800541
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600542 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700543
Chris Yef59a2f42020-10-16 12:55:26 -0700544 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
545 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
546 const std::vector<float>& values) override {}
547
548 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
549 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000550
Chris Yefb552902021-02-03 17:18:37 -0800551 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
552
Prabir Pradhana41d2442023-04-20 21:30:40 +0000553 InputDispatcherConfiguration getDispatcherConfiguration() override { return mConfig; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800554
Prabir Pradhana41d2442023-04-20 21:30:40 +0000555 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700556 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000557 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700558 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000559 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
560 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800561 break;
562 }
563
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700564 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000565 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
566 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800567 break;
568 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700569 default: {
570 ADD_FAILURE() << "Should only filter keys or motions";
571 break;
572 }
Jackal Guof9696682018-10-05 12:23:23 +0800573 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574 return true;
575 }
576
Prabir Pradhana41d2442023-04-20 21:30:40 +0000577 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
578 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800579 // Clear intercept state when we handled the event.
580 mInterceptKeyTimeout = 0ms;
581 }
582 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800583
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600584 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800585
Prabir Pradhana41d2442023-04-20 21:30:40 +0000586 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800587 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
588 // Clear intercept state so we could dispatch the event in next wake.
589 mInterceptKeyTimeout = 0ms;
590 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800591 }
592
Prabir Pradhana41d2442023-04-20 21:30:40 +0000593 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
594 uint32_t) override {
595 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596 }
597
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600598 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
599 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700600 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800601 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
602 * essentially a passthrough for notifySwitch.
603 */
Harry Cutts33476232023-01-30 19:57:29 +0000604 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800605 }
606
Josep del Riob3981622023-04-18 15:49:45 +0000607 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
608 std::scoped_lock lock(mLock);
609 mPokedUserActivity = true;
610 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800611
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600612 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700613 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700614 mOnPointerDownToken = newToken;
615 }
616
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000617 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800618 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000619 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800620 mPointerCaptureChangedCondition.notify_all();
621 }
622
arthurhungf452d0b2021-01-06 00:19:52 +0800623 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
624 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800625 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800626 mDropTargetWindowToken = token;
627 }
628
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000629 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000630 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000631 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
632 }
633
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700634 void assertFilterInputEventWasCalledInternal(
635 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700636 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800637 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700638 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800639 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800640 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800641};
642
Michael Wrightd02c5b62014-02-10 15:10:22 -0800643// --- InputDispatcherTest ---
644
645class InputDispatcherTest : public testing::Test {
646protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000647 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700648 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000650 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000651 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
652 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800653 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000654 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700655 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800656 }
657
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000658 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700659 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000660 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700661 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800662 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700663
664 /**
665 * Used for debugging when writing the test
666 */
667 void dumpDispatcherState() {
668 std::string dump;
669 mDispatcher->dump(dump);
670 std::stringstream ss(dump);
671 std::string to;
672
673 while (std::getline(ss, to, '\n')) {
674 ALOGE("%s", to.c_str());
675 }
676 }
Vishnu Nair958da932020-08-21 17:12:37 -0700677
Chavi Weingarten847e8512023-03-29 00:26:09 +0000678 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700679 FocusRequest request;
680 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000681 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700682 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
683 request.displayId = window->getInfo()->displayId;
684 mDispatcher->setFocusedWindow(request);
685 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800686};
687
Michael Wrightd02c5b62014-02-10 15:10:22 -0800688TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
689 KeyEvent event;
690
691 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800692 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
693 INVALID_HMAC,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600694 /*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
695 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800696 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000697 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000698 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800699 << "Should reject key events with undefined action.";
700
701 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800702 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
703 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600704 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800705 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000706 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000707 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800708 << "Should reject key events with ACTION_MULTIPLE.";
709}
710
711TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
712 MotionEvent event;
713 PointerProperties pointerProperties[MAX_POINTERS + 1];
714 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800715 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716 pointerProperties[i].clear();
717 pointerProperties[i].id = i;
718 pointerCoords[i].clear();
719 }
720
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800721 // Some constants commonly used below
722 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
723 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
724 constexpr int32_t metaState = AMETA_NONE;
725 constexpr MotionClassification classification = MotionClassification::NONE;
726
chaviw9eaa22c2020-07-01 16:21:27 -0700727 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800729 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
chaviw9eaa22c2020-07-01 16:21:27 -0700730 /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
731 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700732 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
733 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700734 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800735 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000736 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000737 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800738 << "Should reject motion events with undefined action.";
739
740 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800741 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800742 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
743 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
744 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
745 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500746 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800747 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000748 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000749 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800750 << "Should reject motion events with pointer down index too large.";
751
Garfield Tanfbe732e2020-01-24 11:26:14 -0800752 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700753 AMOTION_EVENT_ACTION_POINTER_DOWN |
754 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700755 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
756 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700757 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500758 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000760 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000761 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800762 << "Should reject motion events with pointer down index too small.";
763
764 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800765 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800766 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
767 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
768 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
769 ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500770 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800771 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000772 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000773 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800774 << "Should reject motion events with pointer up index too large.";
775
Garfield Tanfbe732e2020-01-24 11:26:14 -0800776 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700777 AMOTION_EVENT_ACTION_POINTER_UP |
778 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700779 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
780 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700781 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
chaviw3277faf2021-05-19 16:45:23 -0500782 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000784 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000785 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800786 << "Should reject motion events with pointer up index too small.";
787
788 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800789 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
790 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700791 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700792 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
793 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700794 /*pointerCount*/ 0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800795 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000796 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000797 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800798 << "Should reject motion events with 0 pointers.";
799
Garfield Tanfbe732e2020-01-24 11:26:14 -0800800 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
801 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700802 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700803 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
804 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700805 /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800806 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000807 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000808 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800809 << "Should reject motion events with more than MAX_POINTERS pointers.";
810
811 // Rejects motion events with invalid pointer ids.
812 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800813 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
814 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700815 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700816 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
817 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700818 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800819 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000820 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000821 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800822 << "Should reject motion events with pointer ids less than 0.";
823
824 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800825 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
826 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700827 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700828 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
829 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700830 /*pointerCount*/ 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800831 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000832 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000833 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800834 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
835
836 // Rejects motion events with duplicate pointer ids.
837 pointerProperties[0].id = 1;
838 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800839 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
840 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700841 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700842 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
843 ARBITRARY_TIME,
Garfield Tan00f511d2019-06-12 16:55:40 -0700844 /*pointerCount*/ 2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800845 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000846 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000847 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800848 << "Should reject motion events with duplicate pointer ids.";
849}
850
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800851/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
852
853TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
854 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000855 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800856 ASSERT_TRUE(mDispatcher->waitForIdle());
857
858 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
859}
860
861TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000862 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
863 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000864 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800865
866 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
867 args.policyFlags |= POLICY_FLAG_TRUSTED;
868 mFakePolicy->assertNotifySwitchWasCalled(args);
869}
870
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700871namespace {
872
Arthur Hungb92218b2018-08-14 12:00:21 +0800873// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700874static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700875// Default input dispatching timeout if there is no focused application or paused window
876// from which to determine an appropriate dispatching timeout.
877static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
878 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
879 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800880
881class FakeApplicationHandle : public InputApplicationHandle {
882public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700883 FakeApplicationHandle() {
884 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700885 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500886 mInfo.dispatchingTimeoutMillis =
887 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700888 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800889 virtual ~FakeApplicationHandle() {}
890
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000891 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700892
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500893 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
894 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700895 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800896};
897
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800898class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800899public:
Garfield Tan15601662020-09-22 15:32:38 -0700900 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800901 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700902 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800903 }
904
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800905 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700906 InputEvent* event;
907 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
908 if (!consumeSeq) {
909 return nullptr;
910 }
911 finishEvent(*consumeSeq);
912 return event;
913 }
914
915 /**
916 * Receive an event without acknowledging it.
917 * Return the sequence number that could later be used to send finished signal.
918 */
919 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800920 uint32_t consumeSeq;
921 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800922
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800923 std::chrono::time_point start = std::chrono::steady_clock::now();
924 status_t status = WOULD_BLOCK;
925 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000926 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800927 &event);
928 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
929 if (elapsed > 100ms) {
930 break;
931 }
932 }
933
934 if (status == WOULD_BLOCK) {
935 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
938
939 if (status != OK) {
940 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700941 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800942 }
943 if (event == nullptr) {
944 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700945 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800946 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700947 if (outEvent != nullptr) {
948 *outEvent = event;
949 }
950 return consumeSeq;
951 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800952
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700953 /**
954 * To be used together with "receiveEvent" to complete the consumption of an event.
955 */
956 void finishEvent(uint32_t consumeSeq) {
957 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
958 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800959 }
960
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000961 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
962 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
963 ASSERT_EQ(OK, status);
964 }
965
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700966 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000967 std::optional<int32_t> expectedDisplayId,
968 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800969 InputEvent* event = consume();
970
971 ASSERT_NE(nullptr, event) << mName.c_str()
972 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800973 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700974 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
975 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800976
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000977 if (expectedDisplayId.has_value()) {
978 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
979 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800980
Tiger Huang8664f8c2018-10-11 19:14:35 +0800981 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700982 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800983 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
984 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000985 if (expectedFlags.has_value()) {
986 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
987 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800988 break;
989 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700990 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800991 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000992 assertMotionAction(expectedAction, motionEvent.getAction());
993
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000994 if (expectedFlags.has_value()) {
995 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
996 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800997 break;
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001000 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1001 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001002 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001003 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1004 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001005 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001006 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1007 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001008 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001009 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1010 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001011 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001012 }
1013
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001014 MotionEvent* consumeMotion() {
1015 InputEvent* event = consume();
1016
1017 if (event == nullptr) {
1018 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1019 return nullptr;
1020 }
1021
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001022 if (event->getType() != InputEventType::MOTION) {
1023 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001024 return nullptr;
1025 }
1026 return static_cast<MotionEvent*>(event);
1027 }
1028
1029 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1030 MotionEvent* motionEvent = consumeMotion();
1031 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1032 ASSERT_THAT(*motionEvent, matcher);
1033 }
1034
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001035 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1036 InputEvent* event = consume();
1037 ASSERT_NE(nullptr, event) << mName.c_str()
1038 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001039 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1040 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001041
1042 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1043 << mName.c_str() << ": event displayId should always be NONE.";
1044
1045 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1046 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001047 }
1048
Prabir Pradhan99987712020-11-10 18:43:05 -08001049 void consumeCaptureEvent(bool hasCapture) {
1050 const InputEvent* event = consume();
1051 ASSERT_NE(nullptr, event) << mName.c_str()
1052 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001053 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1054 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001055
1056 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1057 << mName.c_str() << ": event displayId should always be NONE.";
1058
1059 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1060 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1061 }
1062
arthurhungb89ccb02020-12-30 16:19:01 +08001063 void consumeDragEvent(bool isExiting, float x, float y) {
1064 const InputEvent* event = consume();
1065 ASSERT_NE(nullptr, event) << mName.c_str()
1066 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001067 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001068
1069 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1070 << mName.c_str() << ": event displayId should always be NONE.";
1071
1072 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1073 EXPECT_EQ(isExiting, dragEvent.isExiting());
1074 EXPECT_EQ(x, dragEvent.getX());
1075 EXPECT_EQ(y, dragEvent.getY());
1076 }
1077
Antonio Kantekf16f2832021-09-28 04:39:20 +00001078 void consumeTouchModeEvent(bool inTouchMode) {
1079 const InputEvent* event = consume();
1080 ASSERT_NE(nullptr, event) << mName.c_str()
1081 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001082 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1083 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001084
1085 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1086 << mName.c_str() << ": event displayId should always be NONE.";
1087 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1088 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1089 }
1090
chaviwd1c23182019-12-20 18:44:56 -08001091 void assertNoEvents() {
1092 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001093 if (event == nullptr) {
1094 return;
1095 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001096 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001097 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1098 ADD_FAILURE() << "Received key event "
1099 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001100 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001101 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1102 ADD_FAILURE() << "Received motion event "
1103 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001104 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001105 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1106 ADD_FAILURE() << "Received focus event, hasFocus = "
1107 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001108 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001109 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1110 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1111 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001112 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001113 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1114 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1115 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001116 }
1117 FAIL() << mName.c_str()
1118 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001119 }
1120
1121 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1122
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001123 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1124
chaviwd1c23182019-12-20 18:44:56 -08001125protected:
1126 std::unique_ptr<InputConsumer> mConsumer;
1127 PreallocatedInputEventFactory mEventFactory;
1128
1129 std::string mName;
1130};
1131
chaviw3277faf2021-05-19 16:45:23 -05001132class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001133public:
1134 static const int32_t WIDTH = 600;
1135 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001136
Chris Yea209fde2020-07-22 13:54:51 -07001137 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001138 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001139 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001140 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001141 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001142 base::Result<std::unique_ptr<InputChannel>> channel =
1143 dispatcher->createInputChannel(name);
1144 token = (*channel)->getConnectionToken();
1145 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001146 }
1147
1148 inputApplicationHandle->updateInfo();
1149 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1150
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001151 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001152 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001153 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001154 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001155 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001156 mInfo.frameLeft = 0;
1157 mInfo.frameTop = 0;
1158 mInfo.frameRight = WIDTH;
1159 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001160 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001161 mInfo.globalScaleFactor = 1.0;
1162 mInfo.touchableRegion.clear();
1163 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001164 mInfo.ownerPid = WINDOW_PID;
1165 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001166 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001167 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001168 }
1169
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001170 sp<FakeWindowHandle> clone(int32_t displayId) {
1171 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1172 handle->mInfo = mInfo;
1173 handle->mInfo.displayId = displayId;
1174 handle->mInfo.id = sId++;
1175 handle->mInputReceiver = mInputReceiver;
1176 return handle;
1177 }
1178
1179 /**
1180 * This is different from clone, because clone will make a "mirror" window - a window with the
1181 * same token, but a different ID. The original window and the clone window are allowed to be
1182 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1183 * This function will create a different object of WindowInfoHandle, but with the same
1184 * properties as the original object - including the ID.
1185 * You can use either the old or the new object to consume the events.
1186 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1187 * at the same time inside dispatcher.
1188 */
1189 sp<FakeWindowHandle> duplicate() {
1190 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1191 handle->mInfo = mInfo;
1192 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001193 return handle;
1194 }
1195
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001196 void setTouchable(bool touchable) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1198 }
chaviwd1c23182019-12-20 18:44:56 -08001199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001200 void setFocusable(bool focusable) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1202 }
1203
1204 void setVisible(bool visible) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1206 }
Vishnu Nair958da932020-08-21 17:12:37 -07001207
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001208 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001209 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001210 }
1211
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001212 void setPaused(bool paused) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1214 }
1215
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001216 void setPreventSplitting(bool preventSplitting) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001218 }
1219
1220 void setSlippery(bool slippery) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1222 }
1223
1224 void setWatchOutsideTouch(bool watchOutside) {
1225 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1226 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001227
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001228 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1229
1230 void setInterceptsStylus(bool interceptsStylus) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1232 }
1233
1234 void setDropInput(bool dropInput) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1236 }
1237
1238 void setDropInputIfObscured(bool dropInputIfObscured) {
1239 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1240 }
1241
1242 void setNoInputChannel(bool noInputChannel) {
1243 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1244 }
1245
Josep del Riob3981622023-04-18 15:49:45 +00001246 void setDisableUserActivity(bool disableUserActivity) {
1247 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1248 }
1249
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001250 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1251
chaviw3277faf2021-05-19 16:45:23 -05001252 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001253
Bernardo Rufino7393d172021-02-26 13:56:11 +00001254 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1255
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001256 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001257 mInfo.frameLeft = frame.left;
1258 mInfo.frameTop = frame.top;
1259 mInfo.frameRight = frame.right;
1260 mInfo.frameBottom = frame.bottom;
1261 mInfo.touchableRegion.clear();
1262 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001263
1264 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1265 ui::Transform translate;
1266 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1267 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001268 }
1269
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001270 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1271
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001272 void setIsWallpaper(bool isWallpaper) {
1273 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1274 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001275
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001276 void setDupTouchToWallpaper(bool hasWallpaper) {
1277 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1278 }
chaviwd1c23182019-12-20 18:44:56 -08001279
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001280 void setTrustedOverlay(bool trustedOverlay) {
1281 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1282 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001283
chaviw9eaa22c2020-07-01 16:21:27 -07001284 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1285 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1286 }
1287
1288 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001289
yunho.shinf4a80b82020-11-16 21:13:57 +09001290 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1291
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001292 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001294 }
1295
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001296 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001297 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001298 }
1299
Svet Ganov5d3bc372020-01-26 23:11:07 -08001300 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001301 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001302 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1303 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001304 }
1305
1306 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001307 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001308 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1309 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001310 }
1311
1312 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001313 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001314 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1315 }
1316
1317 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1318 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001319 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001320 expectedFlags);
1321 }
1322
Svet Ganov5d3bc372020-01-26 23:11:07 -08001323 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001324 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1325 int32_t expectedFlags = 0) {
1326 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1327 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001328 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001329 }
1330
1331 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001332 int32_t expectedFlags = 0) {
1333 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1334 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001335 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001336 }
1337
1338 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001339 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001340 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001341 expectedFlags);
1342 }
1343
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001344 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1345 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001346 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001347 expectedFlags);
1348 }
1349
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001350 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1351 int32_t expectedFlags = 0) {
1352 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001353 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001354 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001355 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1356 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1357 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1358 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1359 }
1360
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001361 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1362 ASSERT_NE(mInputReceiver, nullptr)
1363 << "Cannot consume events from a window with no receiver";
1364 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1365 }
1366
Prabir Pradhan99987712020-11-10 18:43:05 -08001367 void consumeCaptureEvent(bool hasCapture) {
1368 ASSERT_NE(mInputReceiver, nullptr)
1369 << "Cannot consume events from a window with no receiver";
1370 mInputReceiver->consumeCaptureEvent(hasCapture);
1371 }
1372
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001373 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1374 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001375 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001376 ASSERT_THAT(*motionEvent, matcher);
1377 }
1378
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001379 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001380 std::optional<int32_t> expectedDisplayId,
1381 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001382 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1383 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1384 expectedFlags);
1385 }
1386
arthurhungb89ccb02020-12-30 16:19:01 +08001387 void consumeDragEvent(bool isExiting, float x, float y) {
1388 mInputReceiver->consumeDragEvent(isExiting, x, y);
1389 }
1390
Antonio Kantekf16f2832021-09-28 04:39:20 +00001391 void consumeTouchModeEvent(bool inTouchMode) {
1392 ASSERT_NE(mInputReceiver, nullptr)
1393 << "Cannot consume events from a window with no receiver";
1394 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1395 }
1396
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001397 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001398 if (mInputReceiver == nullptr) {
1399 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1400 return std::nullopt;
1401 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001402 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001403 }
1404
1405 void finishEvent(uint32_t sequenceNum) {
1406 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1407 mInputReceiver->finishEvent(sequenceNum);
1408 }
1409
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001410 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1411 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1412 mInputReceiver->sendTimeline(inputEventId, timeline);
1413 }
1414
chaviwaf87b3e2019-10-01 16:59:28 -07001415 InputEvent* consume() {
1416 if (mInputReceiver == nullptr) {
1417 return nullptr;
1418 }
1419 return mInputReceiver->consume();
1420 }
1421
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001422 MotionEvent* consumeMotion() {
1423 InputEvent* event = consume();
1424 if (event == nullptr) {
1425 ADD_FAILURE() << "Consume failed : no event";
1426 return nullptr;
1427 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001428 if (event->getType() != InputEventType::MOTION) {
1429 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001430 return nullptr;
1431 }
1432 return static_cast<MotionEvent*>(event);
1433 }
1434
Arthur Hungb92218b2018-08-14 12:00:21 +08001435 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001436 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001437 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001438 return; // Can't receive events if the window does not have input channel
1439 }
1440 ASSERT_NE(nullptr, mInputReceiver)
1441 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001442 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001443 }
1444
chaviwaf87b3e2019-10-01 16:59:28 -07001445 sp<IBinder> getToken() { return mInfo.token; }
1446
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001447 const std::string& getName() { return mName; }
1448
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001449 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001450 mInfo.ownerPid = ownerPid;
1451 mInfo.ownerUid = ownerUid;
1452 }
1453
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00001454 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001455
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001456 void destroyReceiver() { mInputReceiver = nullptr; }
1457
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001458 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1459
chaviwd1c23182019-12-20 18:44:56 -08001460private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001461 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001462 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001463 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001464 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001465 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001466};
1467
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001468std::atomic<int32_t> FakeWindowHandle::sId{1};
1469
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001470static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001471 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001472 int32_t displayId = ADISPLAY_ID_NONE,
1473 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001474 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001475 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001476 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001477 KeyEvent event;
1478 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1479
1480 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001481 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001482 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1483 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001484
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001485 if (!allowKeyRepeat) {
1486 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1487 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001488 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001489 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001490}
1491
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001492static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001493 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001494 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001495}
1496
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001497// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1498// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1499// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001500static InputEventInjectionResult injectKeyDownNoRepeat(
1501 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001502 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001503 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001504 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001505}
1506
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001507static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001508 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001509 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001510}
1511
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001512static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001513 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001514 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001515 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001516 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001517 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1518 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001519}
1520
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001521static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001522 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001523 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001524 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001525 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1526 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001527 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001528 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001529 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001530 MotionEventBuilder motionBuilder =
1531 MotionEventBuilder(action, source)
1532 .displayId(displayId)
1533 .eventTime(eventTime)
1534 .rawXCursorPosition(cursorPosition.x)
1535 .rawYCursorPosition(cursorPosition.y)
1536 .pointer(
1537 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1538 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1539 motionBuilder.downTime(eventTime);
1540 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001541
1542 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001543 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1544 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001545}
1546
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001547static InputEventInjectionResult injectMotionDown(
1548 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1549 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001550 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001551}
1552
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001553static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001554 int32_t source, int32_t displayId,
1555 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001556 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001557}
1558
Jackal Guof9696682018-10-05 12:23:23 +08001559static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1560 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1561 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001562 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakou58ba3d12021-02-11 01:31:07 +00001563 displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A,
1564 KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001565
1566 return args;
1567}
1568
Josep del Riob3981622023-04-18 15:49:45 +00001569static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1570 int32_t displayId = ADISPLAY_ID_NONE) {
1571 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1572 // Define a valid key event.
1573 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1574 displayId, 0, action, /* flags */ 0, AKEYCODE_C, KEY_C, AMETA_META_ON,
1575 currentTime);
1576
1577 return args;
1578}
1579
1580static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1581 int32_t displayId = ADISPLAY_ID_NONE) {
1582 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1583 // Define a valid key event.
1584 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
1585 displayId, 0, action, /* flags */ 0, AKEYCODE_ASSIST, KEY_ASSISTANT,
1586 AMETA_NONE, currentTime);
1587
1588 return args;
1589}
1590
Prabir Pradhan678438e2023-04-13 19:32:51 +00001591[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1592 int32_t displayId,
1593 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001594 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001595 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1596 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1597 }
1598
chaviwd1c23182019-12-20 18:44:56 -08001599 PointerProperties pointerProperties[pointerCount];
1600 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001601
chaviwd1c23182019-12-20 18:44:56 -08001602 for (size_t i = 0; i < pointerCount; i++) {
1603 pointerProperties[i].clear();
1604 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001605 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001606
chaviwd1c23182019-12-20 18:44:56 -08001607 pointerCoords[i].clear();
1608 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1609 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1610 }
Jackal Guof9696682018-10-05 12:23:23 +08001611
1612 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1613 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001614 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Garfield Tan00f511d2019-06-12 16:55:40 -07001615 POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
1616 AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001617 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
1618 pointerCoords, /* xPrecision */ 0, /* yPrecision */ 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001619 AMOTION_EVENT_INVALID_CURSOR_POSITION,
1620 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /* videoFrames */ {});
Jackal Guof9696682018-10-05 12:23:23 +08001621
1622 return args;
1623}
1624
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001625static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1626 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1627}
1628
chaviwd1c23182019-12-20 18:44:56 -08001629static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1630 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1631}
1632
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001633static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1634 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001635 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001636}
1637
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001638} // namespace
1639
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001640/**
1641 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1642 * broken channel.
1643 */
1644TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1646 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001647 sp<FakeWindowHandle>::make(application, mDispatcher,
1648 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001649
1650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1651
1652 // Window closes its channel, but the window remains.
1653 window->destroyReceiver();
1654 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1655}
1656
Arthur Hungb92218b2018-08-14 12:00:21 +08001657TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001659 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1660 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001661
Arthur Hung72d8dc32020-03-28 00:48:39 +00001662 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1664 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001666
1667 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001668 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001669}
1670
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001671TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001673 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1674 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001675
1676 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1677 // Inject a MotionEvent to an unknown display.
1678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1679 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1681
1682 // Window should receive motion event.
1683 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1684}
1685
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001686/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001687 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688 * This test serves as a sanity check for the next test, where setInputWindows is
1689 * called twice.
1690 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001691TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001693 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1694 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001695 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696
1697 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001699 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1700 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001702
1703 // Window should receive motion event.
1704 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1705}
1706
1707/**
1708 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001709 */
1710TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001712 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1713 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001714 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001715
1716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001719 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1720 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001721 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001722
1723 // Window should receive motion event.
1724 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1725}
1726
Arthur Hungb92218b2018-08-14 12:00:21 +08001727// The foreground window should receive the first touch down event.
1728TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001730 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001731 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001732 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001733 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001734
Arthur Hung72d8dc32020-03-28 00:48:39 +00001735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1737 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001739
1740 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001741 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001742 windowSecond->assertNoEvents();
1743}
1744
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001745/**
1746 * Two windows: A top window, and a wallpaper behind the window.
1747 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1748 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001749 * 1. foregroundWindow <-- dup touch to wallpaper
1750 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751 */
1752TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1754 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001755 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001756 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001757 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001758 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001759 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001760
1761 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1763 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1764 {100, 200}))
1765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1766
1767 // Both foreground window and its wallpaper should receive the touch down
1768 foregroundWindow->consumeMotionDown();
1769 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1770
1771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1772 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1773 ADISPLAY_ID_DEFAULT, {110, 200}))
1774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1775
1776 foregroundWindow->consumeMotionMove();
1777 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1778
1779 // Now the foreground window goes away, but the wallpaper stays
1780 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1781 foregroundWindow->consumeMotionCancel();
1782 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1783 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1784}
1785
1786/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001787 * Two fingers down on the window, and lift off the first finger.
1788 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1789 * contains a single pointer.
1790 */
1791TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1793 sp<FakeWindowHandle> window =
1794 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1795
1796 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001797 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1799 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1800 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001801 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001802 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1803 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1804 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1805 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001806 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001807 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1808 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1809 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1810 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001811 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1812 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1813 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1814
1815 // Remove the window. The gesture should be canceled
1816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1817 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1818 window->consumeMotionEvent(
1819 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1820}
1821
1822/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001823 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1824 * with the following differences:
1825 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1826 * clean up the connection.
1827 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1828 * Ensure that there's no crash in the dispatcher.
1829 */
1830TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1832 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001833 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001834 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001835 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001836 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001837 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001838
1839 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1841 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1842 {100, 200}))
1843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1844
1845 // Both foreground window and its wallpaper should receive the touch down
1846 foregroundWindow->consumeMotionDown();
1847 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1848
1849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1850 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1851 ADISPLAY_ID_DEFAULT, {110, 200}))
1852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1853
1854 foregroundWindow->consumeMotionMove();
1855 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1856
1857 // Wallpaper closes its channel, but the window remains.
1858 wallpaperWindow->destroyReceiver();
1859 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1860
1861 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1862 // is no longer valid.
1863 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1864 foregroundWindow->consumeMotionCancel();
1865}
1866
Arthur Hungc539dbb2022-12-08 07:45:36 +00001867class ShouldSplitTouchFixture : public InputDispatcherTest,
1868 public ::testing::WithParamInterface<bool> {};
1869INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1870 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001871/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001872 * A single window that receives touch (on top), and a wallpaper window underneath it.
1873 * The top window gets a multitouch gesture.
1874 * Ensure that wallpaper gets the same gesture.
1875 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001876TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878 sp<FakeWindowHandle> foregroundWindow =
1879 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1880 foregroundWindow->setDupTouchToWallpaper(true);
1881 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001882
1883 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001884 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001885 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001886
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888
1889 // Touch down on top window
1890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1891 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1892 {100, 100}))
1893 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1894
1895 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001896 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001897 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1898
1899 // Second finger down on the top window
1900 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001901 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001902 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001903 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1904 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001905 .build();
1906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1907 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1908 InputEventInjectionSync::WAIT_FOR_RESULT))
1909 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1910
Harry Cutts33476232023-01-30 19:57:29 +00001911 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1912 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001913 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001914
1915 const MotionEvent secondFingerUpEvent =
1916 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1917 .displayId(ADISPLAY_ID_DEFAULT)
1918 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001919 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001921 .build();
1922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1923 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1924 InputEventInjectionSync::WAIT_FOR_RESULT))
1925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1926 foregroundWindow->consumeMotionPointerUp(0);
1927 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1928
1929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001930 injectMotionEvent(mDispatcher,
1931 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1932 AINPUT_SOURCE_TOUCHSCREEN)
1933 .displayId(ADISPLAY_ID_DEFAULT)
1934 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
1935 .pointer(PointerBuilder(/* id */ 1,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001936 ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001937 .x(100)
1938 .y(100))
1939 .build(),
1940 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1942 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1943 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001944}
1945
1946/**
1947 * Two windows: a window on the left and window on the right.
1948 * A third window, wallpaper, is behind both windows, and spans both top windows.
1949 * The first touch down goes to the left window. A second pointer touches down on the right window.
1950 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1951 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1952 * ACTION_POINTER_DOWN(1).
1953 */
1954TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1956 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
1961 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001962 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001964 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965
1966 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001967 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001968 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001969 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001970
1971 mDispatcher->setInputWindows(
1972 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1973
1974 // Touch down on left window
1975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1976 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1977 {100, 100}))
1978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1979
1980 // Both foreground window and its wallpaper should receive the touch down
1981 leftWindow->consumeMotionDown();
1982 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1983
1984 // Second finger down on the right window
1985 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001986 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001987 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001988 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1989 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990 .build();
1991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1992 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1993 InputEventInjectionSync::WAIT_FOR_RESULT))
1994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1995
1996 leftWindow->consumeMotionMove();
1997 // Since the touch is split, right window gets ACTION_DOWN
1998 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001999 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002000 expectedWallpaperFlags);
2001
2002 // Now, leftWindow, which received the first finger, disappears.
2003 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
2004 leftWindow->consumeMotionCancel();
2005 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2006 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2007
2008 // The pointer that's still down on the right window moves, and goes to the right window only.
2009 // As far as the dispatcher's concerned though, both pointers are still present.
2010 const MotionEvent secondFingerMoveEvent =
2011 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2012 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002013 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2014 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002015 .build();
2016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2017 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2018 InputEventInjectionSync::WAIT_FOR_RESULT));
2019 rightWindow->consumeMotionMove();
2020
2021 leftWindow->assertNoEvents();
2022 rightWindow->assertNoEvents();
2023 wallpaperWindow->assertNoEvents();
2024}
2025
Arthur Hungc539dbb2022-12-08 07:45:36 +00002026/**
2027 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2028 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2029 * The right window should receive ACTION_DOWN.
2030 */
2031TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002032 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033 sp<FakeWindowHandle> leftWindow =
2034 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2035 leftWindow->setFrame(Rect(0, 0, 200, 200));
2036 leftWindow->setDupTouchToWallpaper(true);
2037 leftWindow->setSlippery(true);
2038
2039 sp<FakeWindowHandle> rightWindow =
2040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2041 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002042
2043 sp<FakeWindowHandle> wallpaperWindow =
2044 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2045 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002046
Arthur Hungc539dbb2022-12-08 07:45:36 +00002047 mDispatcher->setInputWindows(
2048 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002049
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2052 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002053 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002055
2056 // Both foreground window and its wallpaper should receive the touch down
2057 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002058 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2059
Arthur Hungc539dbb2022-12-08 07:45:36 +00002060 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002062 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2063 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2065
Arthur Hungc539dbb2022-12-08 07:45:36 +00002066 leftWindow->consumeMotionCancel();
2067 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2068 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002069}
2070
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002071/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002072 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2073 * interactive, it might stop sending this flag.
2074 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2075 * to have a consistent input stream.
2076 *
2077 * Test procedure:
2078 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2079 * DOWN (new gesture).
2080 *
2081 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2082 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2083 *
2084 * We technically just need a single window here, but we are using two windows (spy on top and a
2085 * regular window below) to emulate the actual situation where it happens on the device.
2086 */
2087TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2088 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2089 sp<FakeWindowHandle> spyWindow =
2090 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2091 spyWindow->setFrame(Rect(0, 0, 200, 200));
2092 spyWindow->setTrustedOverlay(true);
2093 spyWindow->setSpy(true);
2094
2095 sp<FakeWindowHandle> window =
2096 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2097 window->setFrame(Rect(0, 0, 200, 200));
2098
2099 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2100 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002101
2102 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002103 mDispatcher->notifyMotion(
2104 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2105 .deviceId(touchDeviceId)
2106 .policyFlags(DEFAULT_POLICY_FLAGS)
2107 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2108 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002109
Prabir Pradhan678438e2023-04-13 19:32:51 +00002110 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2111 .deviceId(touchDeviceId)
2112 .policyFlags(DEFAULT_POLICY_FLAGS)
2113 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2114 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2115 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002116 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2117 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2118 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2119 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2120
2121 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002122 mDispatcher->notifyMotion(
2123 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2124 .deviceId(touchDeviceId)
2125 .policyFlags(0)
2126 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2127 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2128 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002129 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2130 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2131
2132 // We don't need to reset the device to reproduce the issue, but the reset event typically
2133 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002134 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002135
2136 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002137 mDispatcher->notifyMotion(
2138 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139 .deviceId(touchDeviceId)
2140 .policyFlags(DEFAULT_POLICY_FLAGS)
2141 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2142 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002143 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2144 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2145
2146 // No more events
2147 spyWindow->assertNoEvents();
2148 window->assertNoEvents();
2149}
2150
2151/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002152 * Two windows: a window on the left and a window on the right.
2153 * Mouse is hovered from the right window into the left window.
2154 * Next, we tap on the left window, where the cursor was last seen.
2155 * The second tap is done onto the right window.
2156 * The mouse and tap are from two different devices.
2157 * We technically don't need to set the downtime / eventtime for these events, but setting these
2158 * explicitly helps during debugging.
2159 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2160 * In the buggy implementation, a tap on the right window would cause a crash.
2161 */
2162TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2164 sp<FakeWindowHandle> leftWindow =
2165 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2166 leftWindow->setFrame(Rect(0, 0, 200, 200));
2167
2168 sp<FakeWindowHandle> rightWindow =
2169 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2170 rightWindow->setFrame(Rect(200, 0, 400, 200));
2171
2172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2173 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2174 // stale.
2175 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2176 const int32_t mouseDeviceId = 6;
2177 const int32_t touchDeviceId = 4;
2178 // Move the cursor from right
2179 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2180 injectMotionEvent(mDispatcher,
2181 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2182 AINPUT_SOURCE_MOUSE)
2183 .deviceId(mouseDeviceId)
2184 .downTime(baseTime + 10)
2185 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002186 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002187 .x(300)
2188 .y(100))
2189 .build()));
2190 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2191
2192 // .. to the left window
2193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2194 injectMotionEvent(mDispatcher,
2195 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2196 AINPUT_SOURCE_MOUSE)
2197 .deviceId(mouseDeviceId)
2198 .downTime(baseTime + 10)
2199 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002200 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002201 .x(110)
2202 .y(100))
2203 .build()));
2204 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2205 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2206 // Now tap the left window
2207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2208 injectMotionEvent(mDispatcher,
2209 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2210 AINPUT_SOURCE_TOUCHSCREEN)
2211 .deviceId(touchDeviceId)
2212 .downTime(baseTime + 40)
2213 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002214 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002215 .x(100)
2216 .y(100))
2217 .build()));
2218 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2219 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2220
2221 // release tap
2222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2223 injectMotionEvent(mDispatcher,
2224 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2225 AINPUT_SOURCE_TOUCHSCREEN)
2226 .deviceId(touchDeviceId)
2227 .downTime(baseTime + 40)
2228 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002229 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002230 .x(100)
2231 .y(100))
2232 .build()));
2233 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2234
2235 // Tap the window on the right
2236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2237 injectMotionEvent(mDispatcher,
2238 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2239 AINPUT_SOURCE_TOUCHSCREEN)
2240 .deviceId(touchDeviceId)
2241 .downTime(baseTime + 60)
2242 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002243 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002244 .x(300)
2245 .y(100))
2246 .build()));
2247 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2248
2249 // release tap
2250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2251 injectMotionEvent(mDispatcher,
2252 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2253 AINPUT_SOURCE_TOUCHSCREEN)
2254 .deviceId(touchDeviceId)
2255 .downTime(baseTime + 60)
2256 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002257 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002258 .x(300)
2259 .y(100))
2260 .build()));
2261 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2262
2263 // No more events
2264 leftWindow->assertNoEvents();
2265 rightWindow->assertNoEvents();
2266}
2267
2268/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002269 * Start hovering in a window. While this hover is still active, make another window appear on top.
2270 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2271 * While the top window is present, the hovering is stopped.
2272 * Later, hovering gets resumed again.
2273 * Ensure that new hover gesture is handled correctly.
2274 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2275 * to the window that's currently being hovered over.
2276 */
2277TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2279 sp<FakeWindowHandle> window =
2280 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2281 window->setFrame(Rect(0, 0, 200, 200));
2282
2283 // Only a single window is present at first
2284 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2285
2286 // Start hovering in the window
2287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2288 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2289 .build());
2290 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2291
2292 // Now, an obscuring window appears!
2293 sp<FakeWindowHandle> obscuringWindow =
2294 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2295 ADISPLAY_ID_DEFAULT,
2296 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2297 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2298 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2299 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2300 obscuringWindow->setNoInputChannel(true);
2301 obscuringWindow->setFocusable(false);
2302 obscuringWindow->setAlpha(1.0);
2303 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2304
2305 // While this new obscuring window is present, the hovering is stopped
2306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2307 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2308 .build());
2309 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2310
2311 // Now the obscuring window goes away.
2312 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2313
2314 // And a new hover gesture starts.
2315 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2316 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2317 .build());
2318 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2319}
2320
2321/**
2322 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2323 * the obscuring window.
2324 */
2325TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2327 sp<FakeWindowHandle> window =
2328 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2329 window->setFrame(Rect(0, 0, 200, 200));
2330
2331 // Only a single window is present at first
2332 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2333
2334 // Start hovering in the window
2335 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2336 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2337 .build());
2338 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2339
2340 // Now, an obscuring window appears!
2341 sp<FakeWindowHandle> obscuringWindow =
2342 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2343 ADISPLAY_ID_DEFAULT,
2344 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2345 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2346 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2347 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2348 obscuringWindow->setNoInputChannel(true);
2349 obscuringWindow->setFocusable(false);
2350 obscuringWindow->setAlpha(1.0);
2351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2352
2353 // While this new obscuring window is present, the hovering continues. The event can't go to the
2354 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2355 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2356 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2357 .build());
2358 obscuringWindow->assertNoEvents();
2359 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2360
2361 // Now the obscuring window goes away.
2362 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2363
2364 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2365 // so it should generate a HOVER_ENTER
2366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2367 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2368 .build());
2369 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2370
2371 // Now the MOVE should be getting dispatched normally
2372 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2373 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2374 .build());
2375 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2376}
2377
2378/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002379 * Two windows: a window on the left and a window on the right.
2380 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2381 * down. Then, on the left window, also place second touch pointer down.
2382 * This test tries to reproduce a crash.
2383 * In the buggy implementation, second pointer down on the left window would cause a crash.
2384 */
2385TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2387 sp<FakeWindowHandle> leftWindow =
2388 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2389 leftWindow->setFrame(Rect(0, 0, 200, 200));
2390
2391 sp<FakeWindowHandle> rightWindow =
2392 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2393 rightWindow->setFrame(Rect(200, 0, 400, 200));
2394
2395 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2396
2397 const int32_t touchDeviceId = 4;
2398 const int32_t mouseDeviceId = 6;
2399 NotifyMotionArgs args;
2400
2401 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2403 .deviceId(mouseDeviceId)
2404 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2405 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002406 leftWindow->consumeMotionEvent(
2407 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2408
2409 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002410 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2411 .deviceId(mouseDeviceId)
2412 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2414 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002415
2416 leftWindow->consumeMotionEvent(
2417 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2418 leftWindow->consumeMotionEvent(
2419 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2420
Prabir Pradhan678438e2023-04-13 19:32:51 +00002421 mDispatcher->notifyMotion(
2422 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2423 .deviceId(mouseDeviceId)
2424 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2425 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2426 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2427 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002428 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2429
2430 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2432 .deviceId(touchDeviceId)
2433 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2434 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002435 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2436
2437 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2438
2439 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002440 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2441 .deviceId(touchDeviceId)
2442 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2443 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2444 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002445 leftWindow->consumeMotionEvent(
2446 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2447 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2448 // current implementation.
2449 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2450 rightWindow->consumeMotionEvent(
2451 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2452
2453 leftWindow->assertNoEvents();
2454 rightWindow->assertNoEvents();
2455}
2456
2457/**
2458 * On a single window, use two different devices: mouse and touch.
2459 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2460 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2461 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2462 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2463 * represent a new gesture.
2464 */
2465TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2467 sp<FakeWindowHandle> window =
2468 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2469 window->setFrame(Rect(0, 0, 400, 400));
2470
2471 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2472
2473 const int32_t touchDeviceId = 4;
2474 const int32_t mouseDeviceId = 6;
2475 NotifyMotionArgs args;
2476
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002477 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2479 .deviceId(touchDeviceId)
2480 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002482 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002483 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2484 .deviceId(touchDeviceId)
2485 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2486 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2487 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002488 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002489 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2490 .deviceId(touchDeviceId)
2491 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2492 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2495 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2496 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2497
2498 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2500 .deviceId(mouseDeviceId)
2501 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2502 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2503 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002504
2505 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002506 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002507 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2508
Prabir Pradhan678438e2023-04-13 19:32:51 +00002509 mDispatcher->notifyMotion(
2510 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2511 .deviceId(mouseDeviceId)
2512 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2513 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2514 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2515 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002516 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2517
2518 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002519 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2520 .deviceId(touchDeviceId)
2521 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2522 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2523 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002524 // The pointer_down event should be ignored
2525 window->assertNoEvents();
2526}
2527
2528/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002529 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2530 * the injected event.
2531 */
2532TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2534 sp<FakeWindowHandle> window =
2535 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2536 window->setFrame(Rect(0, 0, 400, 400));
2537
2538 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2539
2540 const int32_t touchDeviceId = 4;
2541 NotifyMotionArgs args;
2542 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2543 // completion.
2544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2545 injectMotionEvent(mDispatcher,
2546 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2547 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002548 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002549 .x(50)
2550 .y(50))
2551 .build()));
2552 window->consumeMotionEvent(
2553 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2554
2555 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2556 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2558 .deviceId(touchDeviceId)
2559 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2560 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002561
2562 window->consumeMotionEvent(
2563 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2564 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2565}
2566
2567/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002568 * This test is similar to the test above, but the sequence of injected events is different.
2569 *
2570 * Two windows: a window on the left and a window on the right.
2571 * Mouse is hovered over the left window.
2572 * Next, we tap on the left window, where the cursor was last seen.
2573 *
2574 * After that, we inject one finger down onto the right window, and then a second finger down onto
2575 * the left window.
2576 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2577 * window (first), and then another on the left window (second).
2578 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2579 * In the buggy implementation, second finger down on the left window would cause a crash.
2580 */
2581TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2582 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2583 sp<FakeWindowHandle> leftWindow =
2584 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2585 leftWindow->setFrame(Rect(0, 0, 200, 200));
2586
2587 sp<FakeWindowHandle> rightWindow =
2588 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2589 rightWindow->setFrame(Rect(200, 0, 400, 200));
2590
2591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2592
2593 const int32_t mouseDeviceId = 6;
2594 const int32_t touchDeviceId = 4;
2595 // Hover over the left window. Keep the cursor there.
2596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2597 injectMotionEvent(mDispatcher,
2598 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2599 AINPUT_SOURCE_MOUSE)
2600 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002601 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002602 .x(50)
2603 .y(50))
2604 .build()));
2605 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2606
2607 // Tap on left window
2608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2609 injectMotionEvent(mDispatcher,
2610 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2611 AINPUT_SOURCE_TOUCHSCREEN)
2612 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002613 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002614 .x(100)
2615 .y(100))
2616 .build()));
2617
2618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2619 injectMotionEvent(mDispatcher,
2620 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2621 AINPUT_SOURCE_TOUCHSCREEN)
2622 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002623 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002624 .x(100)
2625 .y(100))
2626 .build()));
2627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2628 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2629 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2630
2631 // First finger down on right window
2632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2633 injectMotionEvent(mDispatcher,
2634 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2635 AINPUT_SOURCE_TOUCHSCREEN)
2636 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002637 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002638 .x(300)
2639 .y(100))
2640 .build()));
2641 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2642
2643 // Second finger down on the left window
2644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2645 injectMotionEvent(mDispatcher,
2646 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2647 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002648 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002649 .x(300)
2650 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002651 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002652 .x(100)
2653 .y(100))
2654 .build()));
2655 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2656 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2657
2658 // No more events
2659 leftWindow->assertNoEvents();
2660 rightWindow->assertNoEvents();
2661}
2662
2663/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002664 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2665 * While the touch is down, new hover events from the stylus device should be ignored. After the
2666 * touch is gone, stylus hovering should start working again.
2667 */
2668TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2670 sp<FakeWindowHandle> window =
2671 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2672 window->setFrame(Rect(0, 0, 200, 200));
2673
2674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2675
2676 const int32_t stylusDeviceId = 5;
2677 const int32_t touchDeviceId = 4;
2678 // Start hovering with stylus
2679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2680 injectMotionEvent(mDispatcher,
2681 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2682 AINPUT_SOURCE_STYLUS)
2683 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002684 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002685 .x(50)
2686 .y(50))
2687 .build()));
2688 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2689
2690 // Finger down on the window
2691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2692 injectMotionEvent(mDispatcher,
2693 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2694 AINPUT_SOURCE_TOUCHSCREEN)
2695 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002696 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002697 .x(100)
2698 .y(100))
2699 .build()));
2700 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2701 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2702
2703 // Try to continue hovering with stylus. Since we are already down, injection should fail
2704 ASSERT_EQ(InputEventInjectionResult::FAILED,
2705 injectMotionEvent(mDispatcher,
2706 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2707 AINPUT_SOURCE_STYLUS)
2708 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002709 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002710 .x(50)
2711 .y(50))
2712 .build()));
2713 // No event should be sent. This event should be ignored because a pointer from another device
2714 // is already down.
2715
2716 // Lift up the finger
2717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2718 injectMotionEvent(mDispatcher,
2719 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2720 AINPUT_SOURCE_TOUCHSCREEN)
2721 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002722 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002723 .x(100)
2724 .y(100))
2725 .build()));
2726 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2727
2728 // Now that the touch is gone, stylus hovering should start working again
2729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2730 injectMotionEvent(mDispatcher,
2731 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2732 AINPUT_SOURCE_STYLUS)
2733 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002734 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002735 .x(50)
2736 .y(50))
2737 .build()));
2738 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2739 // No more events
2740 window->assertNoEvents();
2741}
2742
2743/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002744 * A spy window above a window with no input channel.
2745 * Start hovering with a stylus device, and then tap with it.
2746 * Ensure spy window receives the entire sequence.
2747 */
2748TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2750 sp<FakeWindowHandle> spyWindow =
2751 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2752 spyWindow->setFrame(Rect(0, 0, 200, 200));
2753 spyWindow->setTrustedOverlay(true);
2754 spyWindow->setSpy(true);
2755 sp<FakeWindowHandle> window =
2756 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2757 window->setNoInputChannel(true);
2758 window->setFrame(Rect(0, 0, 200, 200));
2759
2760 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2761
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002762 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2764 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2765 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002766 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2767 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002771 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2772
2773 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2778
2779 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2784
2785 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2788 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002789 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2790 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2792 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2793 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002794 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2795
2796 // No more events
2797 spyWindow->assertNoEvents();
2798 window->assertNoEvents();
2799}
2800
2801/**
2802 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2803 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2804 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2805 * While the mouse is down, new move events from the touch device should be ignored.
2806 */
2807TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2809 sp<FakeWindowHandle> spyWindow =
2810 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2811 spyWindow->setFrame(Rect(0, 0, 200, 200));
2812 spyWindow->setTrustedOverlay(true);
2813 spyWindow->setSpy(true);
2814 sp<FakeWindowHandle> window =
2815 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2816 window->setFrame(Rect(0, 0, 200, 200));
2817
2818 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2819
2820 const int32_t mouseDeviceId = 7;
2821 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002822
2823 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2825 .deviceId(mouseDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2827 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002828 spyWindow->consumeMotionEvent(
2829 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2830 window->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2832
2833 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2835 .deviceId(touchDeviceId)
2836 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2837 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002838 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2839 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2840 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2841 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2842
Prabir Pradhan678438e2023-04-13 19:32:51 +00002843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2844 .deviceId(touchDeviceId)
2845 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2846 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002847 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2848 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2849
2850 // Pilfer the stream
2851 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2852 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2853
Prabir Pradhan678438e2023-04-13 19:32:51 +00002854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2855 .deviceId(touchDeviceId)
2856 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2857 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002858 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2859
2860 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002861 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2862 .deviceId(mouseDeviceId)
2863 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2864 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2865 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002866
2867 spyWindow->consumeMotionEvent(
2868 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2869 spyWindow->consumeMotionEvent(
2870 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2871 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2872
Prabir Pradhan678438e2023-04-13 19:32:51 +00002873 mDispatcher->notifyMotion(
2874 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2875 .deviceId(mouseDeviceId)
2876 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2877 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2878 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2879 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002880 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2881 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2882
2883 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2885 .deviceId(mouseDeviceId)
2886 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2887 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2888 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002889 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2890 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2891
2892 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2894 .deviceId(touchDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002897
2898 // No more events
2899 spyWindow->assertNoEvents();
2900 window->assertNoEvents();
2901}
2902
2903/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002904 * On the display, have a single window, and also an area where there's no window.
2905 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2906 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2907 */
2908TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2910 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002911 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002912
2913 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002914
2915 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002916 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002917
2918 mDispatcher->waitForIdle();
2919 window->assertNoEvents();
2920
2921 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002922 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002923 mDispatcher->waitForIdle();
2924 window->consumeMotionDown();
2925}
2926
2927/**
2928 * Same test as above, but instead of touching the empty space, the first touch goes to
2929 * non-touchable window.
2930 */
2931TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2933 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002934 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002935 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2936 window1->setTouchable(false);
2937 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002938 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002939 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2940
2941 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2942
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002943 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002944 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002945
2946 mDispatcher->waitForIdle();
2947 window1->assertNoEvents();
2948 window2->assertNoEvents();
2949
2950 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002951 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002952 mDispatcher->waitForIdle();
2953 window2->consumeMotionDown();
2954}
2955
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002956/**
2957 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2958 * to the event time of the first ACTION_DOWN sent to the particular window.
2959 */
2960TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2962 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002963 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002964 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2965 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002966 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002967 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2968
2969 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2970
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002971 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002972 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002973
2974 mDispatcher->waitForIdle();
2975 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002976 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977 window2->assertNoEvents();
2978 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2979 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2980 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2981
2982 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002983 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002984 mDispatcher->waitForIdle();
2985 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002986 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002987 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2988 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2989 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2990 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2991
2992 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002993 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002994 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002995 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002996
2997 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002998 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002999 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003000 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003001
3002 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3003 window1->consumeMotionMove();
3004 window1->assertNoEvents();
3005
3006 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003007 mDispatcher->notifyMotion(
3008 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003009 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003010 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003011
Prabir Pradhan678438e2023-04-13 19:32:51 +00003012 mDispatcher->notifyMotion(
3013 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003014 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003015 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003016}
3017
Garfield Tandf26e862020-07-01 20:18:19 -07003018TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003020 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003021 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003022 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003023 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003024 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003025 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003026
3027 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3028
3029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3030
3031 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003033 injectMotionEvent(mDispatcher,
3034 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3035 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003036 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003037 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003038 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003039
3040 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003042 injectMotionEvent(mDispatcher,
3043 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3044 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003045 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003046 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003047 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3048 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003049
3050 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003052 injectMotionEvent(mDispatcher,
3053 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3054 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003055 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003056 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003057 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3058 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003059
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003061 injectMotionEvent(mDispatcher,
3062 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3063 AINPUT_SOURCE_MOUSE)
3064 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3065 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003066 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003067 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003068 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003069
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003071 injectMotionEvent(mDispatcher,
3072 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3073 AINPUT_SOURCE_MOUSE)
3074 .buttonState(0)
3075 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003076 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003077 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003078 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003079
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003081 injectMotionEvent(mDispatcher,
3082 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3083 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003084 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003085 .build()));
3086 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3087
3088 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003090 injectMotionEvent(mDispatcher,
3091 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3092 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003093 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003094 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003095 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003096
3097 // No more events
3098 windowLeft->assertNoEvents();
3099 windowRight->assertNoEvents();
3100}
3101
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003102/**
3103 * Put two fingers down (and don't release them) and click the mouse button.
3104 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3105 * currently active gesture should be canceled, and the new one should proceed.
3106 */
3107TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3109 sp<FakeWindowHandle> window =
3110 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3111 window->setFrame(Rect(0, 0, 600, 800));
3112
3113 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3114
3115 const int32_t touchDeviceId = 4;
3116 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003117
3118 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3120 .deviceId(touchDeviceId)
3121 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3122 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003123
Prabir Pradhan678438e2023-04-13 19:32:51 +00003124 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3125 .deviceId(touchDeviceId)
3126 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3127 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3128 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003129 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3130 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3131
3132 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3134 .deviceId(mouseDeviceId)
3135 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3136 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3137 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003138 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3139 WithPointerCount(2u)));
3140 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3141
Prabir Pradhan678438e2023-04-13 19:32:51 +00003142 mDispatcher->notifyMotion(
3143 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3144 .deviceId(mouseDeviceId)
3145 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3146 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3147 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3148 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003149 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3150
3151 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3152 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003153 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3154 .deviceId(touchDeviceId)
3155 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3156 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3157 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003158 window->assertNoEvents();
3159}
3160
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003161TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3163
3164 sp<FakeWindowHandle> spyWindow =
3165 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3166 spyWindow->setFrame(Rect(0, 0, 600, 800));
3167 spyWindow->setTrustedOverlay(true);
3168 spyWindow->setSpy(true);
3169 sp<FakeWindowHandle> window =
3170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3171 window->setFrame(Rect(0, 0, 600, 800));
3172
3173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3175
3176 // Send mouse cursor to the window
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3178 injectMotionEvent(mDispatcher,
3179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3180 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003182 .x(100)
3183 .y(100))
3184 .build()));
3185
3186 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3187 WithSource(AINPUT_SOURCE_MOUSE)));
3188 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3189 WithSource(AINPUT_SOURCE_MOUSE)));
3190
3191 window->assertNoEvents();
3192 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003193}
3194
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003195TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3197
3198 sp<FakeWindowHandle> spyWindow =
3199 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3200 spyWindow->setFrame(Rect(0, 0, 600, 800));
3201 spyWindow->setTrustedOverlay(true);
3202 spyWindow->setSpy(true);
3203 sp<FakeWindowHandle> window =
3204 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3205 window->setFrame(Rect(0, 0, 600, 800));
3206
3207 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3209
3210 // Send mouse cursor to the window
3211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3212 injectMotionEvent(mDispatcher,
3213 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3214 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003215 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003216 .x(100)
3217 .y(100))
3218 .build()));
3219
3220 // Move mouse cursor
3221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3222 injectMotionEvent(mDispatcher,
3223 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3224 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003225 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003226 .x(110)
3227 .y(110))
3228 .build()));
3229
3230 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3231 WithSource(AINPUT_SOURCE_MOUSE)));
3232 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3233 WithSource(AINPUT_SOURCE_MOUSE)));
3234 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3235 WithSource(AINPUT_SOURCE_MOUSE)));
3236 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3237 WithSource(AINPUT_SOURCE_MOUSE)));
3238 // Touch down on the window
3239 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3240 injectMotionEvent(mDispatcher,
3241 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3242 AINPUT_SOURCE_TOUCHSCREEN)
3243 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003244 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003245 .x(200)
3246 .y(200))
3247 .build()));
3248 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3249 WithSource(AINPUT_SOURCE_MOUSE)));
3250 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3251 WithSource(AINPUT_SOURCE_MOUSE)));
3252 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3253 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3254 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3255 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3256
3257 // pilfer the motion, retaining the gesture on the spy window.
3258 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3259 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3260 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3261
3262 // Touch UP on the window
3263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3264 injectMotionEvent(mDispatcher,
3265 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3266 AINPUT_SOURCE_TOUCHSCREEN)
3267 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003268 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003269 .x(200)
3270 .y(200))
3271 .build()));
3272 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3273 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3274
3275 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3276 // to send a new gesture. It should again go to both windows (spy and the window below), just
3277 // like the first gesture did, before pilfering. The window configuration has not changed.
3278
3279 // One more tap - DOWN
3280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3281 injectMotionEvent(mDispatcher,
3282 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3283 AINPUT_SOURCE_TOUCHSCREEN)
3284 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003285 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003286 .x(250)
3287 .y(250))
3288 .build()));
3289 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3290 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3291 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3292 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3293
3294 // Touch UP on the window
3295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3296 injectMotionEvent(mDispatcher,
3297 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3298 AINPUT_SOURCE_TOUCHSCREEN)
3299 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003300 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003301 .x(250)
3302 .y(250))
3303 .build()));
3304 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3305 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3306 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3307 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3308
3309 window->assertNoEvents();
3310 spyWindow->assertNoEvents();
3311}
3312
Garfield Tandf26e862020-07-01 20:18:19 -07003313// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3314// directly in this test.
3315TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003317 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003318 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003319 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003320
3321 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3322
3323 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003326 injectMotionEvent(mDispatcher,
3327 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3328 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003329 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003330 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003331 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003332 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003334 injectMotionEvent(mDispatcher,
3335 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3336 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003337 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003338 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003339 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3340 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003341
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003343 injectMotionEvent(mDispatcher,
3344 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3345 AINPUT_SOURCE_MOUSE)
3346 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3347 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003348 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003349 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003350 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003351
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003353 injectMotionEvent(mDispatcher,
3354 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3355 AINPUT_SOURCE_MOUSE)
3356 .buttonState(0)
3357 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003359 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003360 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003361
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003363 injectMotionEvent(mDispatcher,
3364 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3365 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003366 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003367 .build()));
3368 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3369
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003370 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3371 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3372 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003373 injectMotionEvent(mDispatcher,
3374 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3375 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003376 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003377 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003378 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003379}
3380
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003381/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003382 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3383 * is generated.
3384 */
3385TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3387 sp<FakeWindowHandle> window =
3388 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3389 window->setFrame(Rect(0, 0, 1200, 800));
3390
3391 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3392
3393 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3394
3395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3396 injectMotionEvent(mDispatcher,
3397 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3398 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003399 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003400 .x(300)
3401 .y(400))
3402 .build()));
3403 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3404
3405 // Remove the window, but keep the channel.
3406 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3407 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3408}
3409
3410/**
Daniel Norman2f99cdb2023-08-02 16:39:45 -07003411 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3412 */
3413TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) {
3414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3415 sp<FakeWindowHandle> window =
3416 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3417 window->setFrame(Rect(0, 0, 1200, 800));
3418 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3419 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3420
3421 MotionEventBuilder hoverEnterBuilder =
3422 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3424 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3426 injectMotionEvent(mDispatcher, hoverEnterBuilder.build()));
3427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3428 injectMotionEvent(mDispatcher, hoverEnterBuilder.build()));
3429 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3430 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3431}
3432
3433/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003434 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3435 */
3436TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3438 sp<FakeWindowHandle> window =
3439 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3440 window->setFrame(Rect(0, 0, 100, 100));
3441
3442 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3443
3444 const int32_t mouseDeviceId = 7;
3445 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003446
3447 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003448 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3449 .deviceId(mouseDeviceId)
3450 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3451 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003452 window->consumeMotionEvent(
3453 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3454
3455 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3457 .deviceId(touchDeviceId)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3459 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003460
3461 window->consumeMotionEvent(
3462 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3463 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3464}
3465
3466/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003467 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003468 * The tap causes a HOVER_EXIT event to be generated because the current event
3469 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003470 */
3471TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3473 sp<FakeWindowHandle> window =
3474 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3475 window->setFrame(Rect(0, 0, 100, 100));
3476
3477 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3478
3479 // Inject a hover_move from mouse.
3480 NotifyMotionArgs motionArgs =
3481 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3482 ADISPLAY_ID_DEFAULT, {{50, 50}});
3483 motionArgs.xCursorPosition = 50;
3484 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003485 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003486 ASSERT_NO_FATAL_FAILURE(
3487 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3488 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003489
3490 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003491 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3492 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3493 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003494 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003495 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3496 WithSource(AINPUT_SOURCE_MOUSE))));
3497
3498 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003499 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3500 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3501
Prabir Pradhan678438e2023-04-13 19:32:51 +00003502 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3503 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003504 ASSERT_NO_FATAL_FAILURE(
3505 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3506 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3507}
3508
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003509TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3511 sp<FakeWindowHandle> windowDefaultDisplay =
3512 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3513 ADISPLAY_ID_DEFAULT);
3514 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3515 sp<FakeWindowHandle> windowSecondDisplay =
3516 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3517 SECOND_DISPLAY_ID);
3518 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3519
3520 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3521 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3522
3523 // Set cursor position in window in default display and check that hover enter and move
3524 // events are generated.
3525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3526 injectMotionEvent(mDispatcher,
3527 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3528 AINPUT_SOURCE_MOUSE)
3529 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003530 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003531 .x(300)
3532 .y(600))
3533 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003534 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003535
3536 // Remove all windows in secondary display and check that no event happens on window in
3537 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003538 mDispatcher->setInputWindows(
3539 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003540 windowDefaultDisplay->assertNoEvents();
3541
3542 // Move cursor position in window in default display and check that only hover move
3543 // event is generated and not hover enter event.
3544 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3545 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3547 injectMotionEvent(mDispatcher,
3548 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3549 AINPUT_SOURCE_MOUSE)
3550 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003551 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003552 .x(400)
3553 .y(700))
3554 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003555 windowDefaultDisplay->consumeMotionEvent(
3556 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3557 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003558 windowDefaultDisplay->assertNoEvents();
3559}
3560
Garfield Tan00f511d2019-06-12 16:55:40 -07003561TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003562 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003563
3564 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003565 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003566 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003567 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003568 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003569 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003570
3571 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3572
Arthur Hung72d8dc32020-03-28 00:48:39 +00003573 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003574
3575 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3576 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003578 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003579 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003580 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003581 windowRight->assertNoEvents();
3582}
3583
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003584TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003586 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3587 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003588 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003589
Arthur Hung72d8dc32020-03-28 00:48:39 +00003590 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003591 setFocusedWindow(window);
3592
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003593 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003594
Prabir Pradhan678438e2023-04-13 19:32:51 +00003595 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003596
3597 // Window should receive key down event.
3598 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3599
3600 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3601 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003602 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003603 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003604 AKEY_EVENT_FLAG_CANCELED);
3605}
3606
3607TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003608 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003609 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3610 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003611
Arthur Hung72d8dc32020-03-28 00:48:39 +00003612 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003613
Prabir Pradhan678438e2023-04-13 19:32:51 +00003614 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3615 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003616
3617 // Window should receive motion down event.
3618 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3619
3620 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3621 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003622 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003623 window->consumeMotionEvent(
3624 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003625}
3626
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003627TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3629 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3630 "Fake Window", ADISPLAY_ID_DEFAULT);
3631
3632 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3633
3634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3635 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3636 .build());
3637
3638 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3639
3640 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3641 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3642 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3643
3644 // After the device has been reset, a new hovering stream can be sent to the window
3645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3646 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3647 .build());
3648 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3649}
3650
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003651TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
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 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003663 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3664 const nsecs_t injectTime = keyArgs.eventTime;
3665 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003666 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003667 // The dispatching time should be always greater than or equal to intercept key timeout.
3668 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3669 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3670 std::chrono::nanoseconds(interceptKeyTimeout).count());
3671}
3672
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003673/**
3674 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3675 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003676TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003678 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3679 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003680 window->setFocusable(true);
3681
3682 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3683 setFocusedWindow(window);
3684
3685 window->consumeFocusEvent(true);
3686
Prabir Pradhan678438e2023-04-13 19:32:51 +00003687 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003688 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003689
3690 // Set a value that's significantly larger than the default consumption timeout. If the
3691 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3692 mFakePolicy->setInterceptKeyTimeout(600ms);
3693 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3694 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003695 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3696}
3697
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003698/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003699 * Two windows. First is a regular window. Second does not overlap with the first, and has
3700 * WATCH_OUTSIDE_TOUCH.
3701 * Both windows are owned by the same UID.
3702 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3703 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3704 */
3705TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3707 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3708 "First Window", ADISPLAY_ID_DEFAULT);
3709 window->setFrame(Rect{0, 0, 100, 100});
3710
3711 sp<FakeWindowHandle> outsideWindow =
3712 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3713 ADISPLAY_ID_DEFAULT);
3714 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3715 outsideWindow->setWatchOutsideTouch(true);
3716 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3718
3719 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003720 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3721 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3722 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003723 window->consumeMotionDown();
3724 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3725 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3726 outsideWindow->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3728}
3729
3730/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003731 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3732 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3733 * ACTION_OUTSIDE event is sent per gesture.
3734 */
3735TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3736 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003738 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3739 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003740 window->setWatchOutsideTouch(true);
3741 window->setFrame(Rect{0, 0, 100, 100});
3742 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003743 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3744 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003745 secondWindow->setFrame(Rect{100, 100, 200, 200});
3746 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003747 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3748 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003749 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3751
3752 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003753 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3754 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3755 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003756 window->assertNoEvents();
3757 secondWindow->assertNoEvents();
3758
3759 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3760 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003761 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3762 ADISPLAY_ID_DEFAULT,
3763 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003764 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3765 window->consumeMotionEvent(
3766 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003767 secondWindow->consumeMotionDown();
3768 thirdWindow->assertNoEvents();
3769
3770 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3771 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003772 mDispatcher->notifyMotion(
3773 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3774 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003775 window->assertNoEvents();
3776 secondWindow->consumeMotionMove();
3777 thirdWindow->consumeMotionDown();
3778}
3779
Prabir Pradhan814fe082022-07-22 20:22:18 +00003780TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003782 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3783 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003784 window->setFocusable(true);
3785
Patrick Williamsd828f302023-04-28 17:52:08 -05003786 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003787 setFocusedWindow(window);
3788
3789 window->consumeFocusEvent(true);
3790
Prabir Pradhan678438e2023-04-13 19:32:51 +00003791 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3792 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3793 mDispatcher->notifyKey(keyDown);
3794 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003795
3796 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3797 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3798
3799 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003800 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003801
3802 window->consumeFocusEvent(false);
3803
Prabir Pradhan678438e2023-04-13 19:32:51 +00003804 mDispatcher->notifyKey(keyDown);
3805 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003806 window->assertNoEvents();
3807}
3808
Arthur Hung96483742022-11-15 03:30:48 +00003809TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3811 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3812 "Fake Window", ADISPLAY_ID_DEFAULT);
3813 // Ensure window is non-split and have some transform.
3814 window->setPreventSplitting(true);
3815 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003817
3818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3819 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3820 {50, 50}))
3821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3822 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3823
3824 const MotionEvent secondFingerDownEvent =
3825 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3826 .displayId(ADISPLAY_ID_DEFAULT)
3827 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003828 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3829 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003830 .build();
3831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3832 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3833 InputEventInjectionSync::WAIT_FOR_RESULT))
3834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3835
3836 const MotionEvent* event = window->consumeMotion();
3837 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3838 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3839 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3840 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3841 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3842}
3843
Harry Cuttsb166c002023-05-09 13:06:05 +00003844TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3845 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3846 sp<FakeWindowHandle> window =
3847 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3848 window->setFrame(Rect(0, 0, 400, 400));
3849 sp<FakeWindowHandle> trustedOverlay =
3850 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3851 ADISPLAY_ID_DEFAULT);
3852 trustedOverlay->setSpy(true);
3853 trustedOverlay->setTrustedOverlay(true);
3854
3855 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3856
3857 // Start a three-finger touchpad swipe
3858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3859 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3860 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3861 .build());
3862 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3863 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3864 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3865 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3866 .build());
3867 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3868 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3869 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3870 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3871 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3872 .build());
3873
3874 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3875 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3876 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3877
3878 // Move the swipe a bit
3879 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3880 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3881 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3882 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3883 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3884 .build());
3885
3886 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3887
3888 // End the swipe
3889 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3891 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3892 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3893 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3894 .build());
3895 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3896 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3897 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3898 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3899 .build());
3900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3901 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3902 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3903 .build());
3904
3905 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3906 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3907 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3908
3909 window->assertNoEvents();
3910}
3911
3912TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3914 sp<FakeWindowHandle> window =
3915 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3916 window->setFrame(Rect(0, 0, 400, 400));
3917 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3918
3919 // Start a three-finger touchpad swipe
3920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3921 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3922 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3923 .build());
3924 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3925 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3926 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3927 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3928 .build());
3929 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3930 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3931 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3932 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3933 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3934 .build());
3935
3936 // Move the swipe a bit
3937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3938 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3939 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3940 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3941 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3942 .build());
3943
3944 // End the swipe
3945 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3946 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3947 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3948 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3949 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3950 .build());
3951 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3952 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3953 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3954 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3955 .build());
3956 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3957 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3958 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3959 .build());
3960
3961 window->assertNoEvents();
3962}
3963
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003964/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003965 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3966 * the first pointer.
3967 * Ensure that the second pointer is not sent to the window.
3968 *
3969 * The subsequent gesture should be correctly delivered to the window.
3970 */
3971TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3973 sp<FakeWindowHandle> window =
3974 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3975 window->setFrame(Rect(0, 0, 400, 400));
3976 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3977
3978 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3980 .downTime(baseTime + 10)
3981 .eventTime(baseTime + 10)
3982 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3983 .build());
3984
3985 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3986
3987 // We need a new window object for the same window, because dispatcher will store objects by
3988 // reference. That means that the testing code and the dispatcher will refer to the same shared
3989 // object. Calling window->setTransform here would affect dispatcher's comparison
3990 // of the old window to the new window, since both the old window and the new window would be
3991 // updated to the same value.
3992 sp<FakeWindowHandle> windowDup = window->duplicate();
3993
3994 // Change the transform so that the orientation is now different from original.
3995 windowDup->setWindowTransform(0, -1, 1, 0);
3996
3997 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3998
3999 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
4000
4001 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4002 .downTime(baseTime + 10)
4003 .eventTime(baseTime + 30)
4004 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4005 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4006 .build());
4007
4008 // Finish the gesture and start a new one. Ensure the new gesture is sent to the window
4009 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4010 .downTime(baseTime + 10)
4011 .eventTime(baseTime + 40)
4012 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4013 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4014 .build());
4015 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4016 .downTime(baseTime + 10)
4017 .eventTime(baseTime + 50)
4018 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4019 .build());
4020
4021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4022 .downTime(baseTime + 60)
4023 .eventTime(baseTime + 60)
4024 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4025 .build());
4026
4027 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4028}
4029
4030/**
Hu Guoca59f112023-09-17 20:51:08 +08004031 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4032 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4033 * its coordinates should be converted by the transform of the windows of target screen.
4034 */
4035TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4036 // This case will create a window and a spy window on the default display and mirror
4037 // window on the second display. cancel event is sent through spy window pilferPointers
4038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4039
4040 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4041 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4042 spyWindowDefaultDisplay->setTrustedOverlay(true);
4043 spyWindowDefaultDisplay->setSpy(true);
4044
4045 sp<FakeWindowHandle> windowDefaultDisplay =
4046 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4047 ADISPLAY_ID_DEFAULT);
4048 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4049
4050 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4051 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4052
4053 // Add the windows to the dispatcher
4054 mDispatcher->onWindowInfosChanged(
4055 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4056 *windowSecondDisplay->getInfo()},
4057 {},
4058 0,
4059 0});
4060
4061 // Send down to ADISPLAY_ID_DEFAULT
4062 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4063 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4064 {100, 100}))
4065 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4066
4067 spyWindowDefaultDisplay->consumeMotionDown();
4068 windowDefaultDisplay->consumeMotionDown();
4069
4070 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4071
4072 // windowDefaultDisplay gets cancel
4073 MotionEvent* event = windowDefaultDisplay->consumeMotion();
4074 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
4075
4076 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4077 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4078 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4079 // SECOND_DISPLAY_ID, the x and y coordinates are 200
4080 EXPECT_EQ(100, event->getX(0));
4081 EXPECT_EQ(100, event->getY(0));
4082}
4083
4084/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004085 * Ensure the correct coordinate spaces are used by InputDispatcher.
4086 *
4087 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4088 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4089 * space.
4090 */
4091class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4092public:
4093 void SetUp() override {
4094 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004095 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004096 }
4097
4098 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4099 gui::DisplayInfo info;
4100 info.displayId = displayId;
4101 info.transform = transform;
4102 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004103 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004104 }
4105
4106 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4107 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004108 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004109 }
4110
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004111 void removeAllWindowsAndDisplays() {
4112 mDisplayInfos.clear();
4113 mWindowInfos.clear();
4114 }
4115
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004116 // Set up a test scenario where the display has a scaled projection and there are two windows
4117 // on the display.
4118 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4119 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4120 // respectively.
4121 ui::Transform displayTransform;
4122 displayTransform.set(2, 0, 0, 4);
4123 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4124
4125 std::shared_ptr<FakeApplicationHandle> application =
4126 std::make_shared<FakeApplicationHandle>();
4127
4128 // Add two windows to the display. Their frames are represented in the display space.
4129 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004130 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4131 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004132 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4133 addWindow(firstWindow);
4134
4135 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004136 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4137 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004138 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4139 addWindow(secondWindow);
4140 return {std::move(firstWindow), std::move(secondWindow)};
4141 }
4142
4143private:
4144 std::vector<gui::DisplayInfo> mDisplayInfos;
4145 std::vector<gui::WindowInfo> mWindowInfos;
4146};
4147
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004148TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004149 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4150 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004151 // selected so that if the hit test was performed with the point and the bounds being in
4152 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004153 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4154 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4155 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004156
4157 firstWindow->consumeMotionDown();
4158 secondWindow->assertNoEvents();
4159}
4160
4161// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4162// the event should be treated as being in the logical display space.
4163TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4164 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4165 // Send down to the first window. The point is represented in the logical display space. The
4166 // point is selected so that if the hit test was done in logical display space, then it would
4167 // end up in the incorrect window.
4168 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4169 PointF{75 * 2, 55 * 4});
4170
4171 firstWindow->consumeMotionDown();
4172 secondWindow->assertNoEvents();
4173}
4174
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004175// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4176// event should be treated as being in the logical display space.
4177TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4178 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4179
4180 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4181 ui::Transform injectedEventTransform;
4182 injectedEventTransform.set(matrix);
4183 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4184 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4185
4186 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4187 .displayId(ADISPLAY_ID_DEFAULT)
4188 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004189 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004190 .x(untransformedPoint.x)
4191 .y(untransformedPoint.y))
4192 .build();
4193 event.transform(matrix);
4194
4195 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4196 InputEventInjectionSync::WAIT_FOR_RESULT);
4197
4198 firstWindow->consumeMotionDown();
4199 secondWindow->assertNoEvents();
4200}
4201
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004202TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4203 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4204
4205 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004206 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4207 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4208 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004209
4210 firstWindow->assertNoEvents();
4211 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004212 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004213 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4214
4215 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4216 EXPECT_EQ(300, event->getRawX(0));
4217 EXPECT_EQ(880, event->getRawY(0));
4218
4219 // Ensure that the x and y values are in the window's coordinate space.
4220 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4221 // the logical display space. This will be the origin of the window space.
4222 EXPECT_EQ(100, event->getX(0));
4223 EXPECT_EQ(80, event->getY(0));
4224}
4225
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004226/** Ensure consistent behavior of InputDispatcher in all orientations. */
4227class InputDispatcherDisplayOrientationFixture
4228 : public InputDispatcherDisplayProjectionTest,
4229 public ::testing::WithParamInterface<ui::Rotation> {};
4230
4231// This test verifies the touchable region of a window for all rotations of the display by tapping
4232// in different locations on the display, specifically points close to the four corners of a
4233// window.
4234TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4235 constexpr static int32_t displayWidth = 400;
4236 constexpr static int32_t displayHeight = 800;
4237
4238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4239
4240 const auto rotation = GetParam();
4241
4242 // Set up the display with the specified rotation.
4243 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4244 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4245 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4246 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4247 logicalDisplayWidth, logicalDisplayHeight);
4248 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4249
4250 // Create a window with its bounds determined in the logical display.
4251 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4252 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4253 sp<FakeWindowHandle> window =
4254 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4255 window->setFrame(frameInDisplay, displayTransform);
4256 addWindow(window);
4257
4258 // The following points in logical display space should be inside the window.
4259 static const std::array<vec2, 4> insidePoints{
4260 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4261 for (const auto pointInsideWindow : insidePoints) {
4262 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4263 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004264 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4265 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4266 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004267 window->consumeMotionDown();
4268
Prabir Pradhan678438e2023-04-13 19:32:51 +00004269 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4270 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4271 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004272 window->consumeMotionUp();
4273 }
4274
4275 // The following points in logical display space should be outside the window.
4276 static const std::array<vec2, 5> outsidePoints{
4277 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4278 for (const auto pointOutsideWindow : outsidePoints) {
4279 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4280 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004281 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4282 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4283 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004284
Prabir Pradhan678438e2023-04-13 19:32:51 +00004285 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4286 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4287 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004288 }
4289 window->assertNoEvents();
4290}
4291
4292// Run the precision tests for all rotations.
4293INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4294 InputDispatcherDisplayOrientationFixture,
4295 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4296 ui::ROTATION_270),
4297 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4298 return ftl::enum_string(testParamInfo.param);
4299 });
4300
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004301using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4302 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004303
4304class TransferTouchFixture : public InputDispatcherTest,
4305 public ::testing::WithParamInterface<TransferFunction> {};
4306
4307TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004309
4310 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004311 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004312 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4313 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004314 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004315 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004316 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4317 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004318 sp<FakeWindowHandle> wallpaper =
4319 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4320 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004321 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004323
4324 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004325 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4326 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004327
Svet Ganov5d3bc372020-01-26 23:11:07 -08004328 // Only the first window should get the down event
4329 firstWindow->consumeMotionDown();
4330 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004331 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004332
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004333 // Transfer touch to the second window
4334 TransferFunction f = GetParam();
4335 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4336 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004337 // The first window gets cancel and the second gets down
4338 firstWindow->consumeMotionCancel();
4339 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004340 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004341
4342 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004343 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4344 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004345 // The first window gets no events and the second gets up
4346 firstWindow->assertNoEvents();
4347 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004348 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004349}
4350
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004351/**
4352 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4353 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4354 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4355 * natural to the user.
4356 * In this test, we are sending a pointer to both spy window and first window. We then try to
4357 * transfer touch to the second window. The dispatcher should identify the first window as the
4358 * one that should lose the gesture, and therefore the action should be to move the gesture from
4359 * the first window to the second.
4360 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4361 * the other API, as well.
4362 */
4363TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4365
4366 // Create a couple of windows + a spy window
4367 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004368 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004369 spyWindow->setTrustedOverlay(true);
4370 spyWindow->setSpy(true);
4371 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004372 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004373 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004374 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004375
4376 // Add the windows to the dispatcher
4377 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4378
4379 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004380 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4381 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004382 // Only the first window and spy should get the down event
4383 spyWindow->consumeMotionDown();
4384 firstWindow->consumeMotionDown();
4385
4386 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4387 // if f === 'transferTouch'.
4388 TransferFunction f = GetParam();
4389 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4390 ASSERT_TRUE(success);
4391 // The first window gets cancel and the second gets down
4392 firstWindow->consumeMotionCancel();
4393 secondWindow->consumeMotionDown();
4394
4395 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4397 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004398 // The first window gets no events and the second+spy get up
4399 firstWindow->assertNoEvents();
4400 spyWindow->consumeMotionUp();
4401 secondWindow->consumeMotionUp();
4402}
4403
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004404TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004406
4407 PointF touchPoint = {10, 10};
4408
4409 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004410 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004411 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4412 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004413 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004414 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004415 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4416 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004417 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004418
4419 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004421
4422 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4424 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4425 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004426 // Only the first window should get the down event
4427 firstWindow->consumeMotionDown();
4428 secondWindow->assertNoEvents();
4429
4430 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004431 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4432 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004433 // Only the first window should get the pointer down event
4434 firstWindow->consumeMotionPointerDown(1);
4435 secondWindow->assertNoEvents();
4436
4437 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004438 TransferFunction f = GetParam();
4439 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4440 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004441 // The first window gets cancel and the second gets down and pointer down
4442 firstWindow->consumeMotionCancel();
4443 secondWindow->consumeMotionDown();
4444 secondWindow->consumeMotionPointerDown(1);
4445
4446 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004447 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4448 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004449 // The first window gets nothing and the second gets pointer up
4450 firstWindow->assertNoEvents();
4451 secondWindow->consumeMotionPointerUp(1);
4452
4453 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004454 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4455 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004456 // The first window gets nothing and the second gets up
4457 firstWindow->assertNoEvents();
4458 secondWindow->consumeMotionUp();
4459}
4460
Arthur Hungc539dbb2022-12-08 07:45:36 +00004461TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4462 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4463
4464 // Create a couple of windows
4465 sp<FakeWindowHandle> firstWindow =
4466 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4467 ADISPLAY_ID_DEFAULT);
4468 firstWindow->setDupTouchToWallpaper(true);
4469 sp<FakeWindowHandle> secondWindow =
4470 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4471 ADISPLAY_ID_DEFAULT);
4472 secondWindow->setDupTouchToWallpaper(true);
4473
4474 sp<FakeWindowHandle> wallpaper1 =
4475 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4476 wallpaper1->setIsWallpaper(true);
4477
4478 sp<FakeWindowHandle> wallpaper2 =
4479 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4480 wallpaper2->setIsWallpaper(true);
4481 // Add the windows to the dispatcher
4482 mDispatcher->setInputWindows(
4483 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4484
4485 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004486 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4487 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004488
4489 // Only the first window should get the down event
4490 firstWindow->consumeMotionDown();
4491 secondWindow->assertNoEvents();
4492 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4493 wallpaper2->assertNoEvents();
4494
4495 // Transfer touch focus to the second window
4496 TransferFunction f = GetParam();
4497 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4498 ASSERT_TRUE(success);
4499
4500 // The first window gets cancel and the second gets down
4501 firstWindow->consumeMotionCancel();
4502 secondWindow->consumeMotionDown();
4503 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4504 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4505
4506 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004507 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4508 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004509 // The first window gets no events and the second gets up
4510 firstWindow->assertNoEvents();
4511 secondWindow->consumeMotionUp();
4512 wallpaper1->assertNoEvents();
4513 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4514}
4515
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004516// For the cases of single pointer touch and two pointers non-split touch, the api's
4517// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4518// for the case where there are multiple pointers split across several windows.
4519INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4520 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004521 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4522 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004523 return dispatcher->transferTouch(destChannelToken,
4524 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004525 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004526 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4527 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004528 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004529 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004530 }));
4531
Svet Ganov5d3bc372020-01-26 23:11:07 -08004532TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004534
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004535 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004536 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4537 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004538 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004539
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004540 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004541 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4542 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004543 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004544
4545 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004546 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004547
4548 PointF pointInFirst = {300, 200};
4549 PointF pointInSecond = {300, 600};
4550
4551 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004552 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4553 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4554 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004555 // Only the first window should get the down event
4556 firstWindow->consumeMotionDown();
4557 secondWindow->assertNoEvents();
4558
4559 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004560 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4561 ADISPLAY_ID_DEFAULT,
4562 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004563 // The first window gets a move and the second a down
4564 firstWindow->consumeMotionMove();
4565 secondWindow->consumeMotionDown();
4566
4567 // Transfer touch focus to the second window
4568 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4569 // The first window gets cancel and the new gets pointer down (it already saw down)
4570 firstWindow->consumeMotionCancel();
4571 secondWindow->consumeMotionPointerDown(1);
4572
4573 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004574 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4575 ADISPLAY_ID_DEFAULT,
4576 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004577 // The first window gets nothing and the second gets pointer up
4578 firstWindow->assertNoEvents();
4579 secondWindow->consumeMotionPointerUp(1);
4580
4581 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004582 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4583 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004584 // The first window gets nothing and the second gets up
4585 firstWindow->assertNoEvents();
4586 secondWindow->consumeMotionUp();
4587}
4588
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004589// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4590// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4591// touch is not supported, so the touch should continue on those windows and the transferred-to
4592// window should get nothing.
4593TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4595
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004596 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004597 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4598 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004599 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004600
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004601 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004602 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4603 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004604 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004605
4606 // Add the windows to the dispatcher
4607 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4608
4609 PointF pointInFirst = {300, 200};
4610 PointF pointInSecond = {300, 600};
4611
4612 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004613 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4614 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4615 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004616 // Only the first window should get the down event
4617 firstWindow->consumeMotionDown();
4618 secondWindow->assertNoEvents();
4619
4620 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004621 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4622 ADISPLAY_ID_DEFAULT,
4623 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004624 // The first window gets a move and the second a down
4625 firstWindow->consumeMotionMove();
4626 secondWindow->consumeMotionDown();
4627
4628 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004629 const bool transferred =
4630 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004631 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4632 ASSERT_FALSE(transferred);
4633 firstWindow->assertNoEvents();
4634 secondWindow->assertNoEvents();
4635
4636 // The rest of the dispatch should proceed as normal
4637 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004638 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4639 ADISPLAY_ID_DEFAULT,
4640 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004641 // The first window gets MOVE and the second gets pointer up
4642 firstWindow->consumeMotionMove();
4643 secondWindow->consumeMotionUp();
4644
4645 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004646 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4647 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004648 // The first window gets nothing and the second gets up
4649 firstWindow->consumeMotionUp();
4650 secondWindow->assertNoEvents();
4651}
4652
Arthur Hungabbb9d82021-09-01 14:52:30 +00004653// This case will create two windows and one mirrored window on the default display and mirror
4654// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4655// the windows info of second display before default display.
4656TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4658 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004659 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004660 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004661 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004662 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004663 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004664
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004665 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004666 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004667
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004668 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004669 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004670
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004671 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004672 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004673
4674 // Update window info, let it find window handle of second display first.
4675 mDispatcher->setInputWindows(
4676 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4677 {ADISPLAY_ID_DEFAULT,
4678 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4679
4680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4681 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4682 {50, 50}))
4683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4684
4685 // Window should receive motion event.
4686 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4687
4688 // Transfer touch focus
4689 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4690 secondWindowInPrimary->getToken()));
4691 // The first window gets cancel.
4692 firstWindowInPrimary->consumeMotionCancel();
4693 secondWindowInPrimary->consumeMotionDown();
4694
4695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4696 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4697 ADISPLAY_ID_DEFAULT, {150, 50}))
4698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4699 firstWindowInPrimary->assertNoEvents();
4700 secondWindowInPrimary->consumeMotionMove();
4701
4702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4703 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4704 {150, 50}))
4705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4706 firstWindowInPrimary->assertNoEvents();
4707 secondWindowInPrimary->consumeMotionUp();
4708}
4709
4710// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4711// 'transferTouch' api.
4712TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4714 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004715 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004716 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004717 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004718 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004719 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004720
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004721 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004722 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004723
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004724 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004725 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004726
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004727 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004728 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004729
4730 // Update window info, let it find window handle of second display first.
4731 mDispatcher->setInputWindows(
4732 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4733 {ADISPLAY_ID_DEFAULT,
4734 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4735
4736 // Touch on second display.
4737 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4738 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4740
4741 // Window should receive motion event.
4742 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4743
4744 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004745 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004746
4747 // The first window gets cancel.
4748 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4749 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4750
4751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4752 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4753 SECOND_DISPLAY_ID, {150, 50}))
4754 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4755 firstWindowInPrimary->assertNoEvents();
4756 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4757
4758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4759 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4761 firstWindowInPrimary->assertNoEvents();
4762 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4763}
4764
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004765TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004767 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4768 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004769
Vishnu Nair47074b82020-08-14 11:54:47 -07004770 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004772 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004773
4774 window->consumeFocusEvent(true);
4775
Prabir Pradhan678438e2023-04-13 19:32:51 +00004776 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004777
4778 // Window should receive key down event.
4779 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004780
4781 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004782 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004783 mFakePolicy->assertUserActivityPoked();
4784}
4785
4786TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4789 "Fake Window", ADISPLAY_ID_DEFAULT);
4790
4791 window->setDisableUserActivity(true);
4792 window->setFocusable(true);
4793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4794 setFocusedWindow(window);
4795
4796 window->consumeFocusEvent(true);
4797
4798 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4799
4800 // Window should receive key down event.
4801 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4802
4803 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004804 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004805 mFakePolicy->assertUserActivityNotPoked();
4806}
4807
4808TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4810 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4811 "Fake Window", ADISPLAY_ID_DEFAULT);
4812
4813 window->setFocusable(true);
4814 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4815 setFocusedWindow(window);
4816
4817 window->consumeFocusEvent(true);
4818
4819 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4820 mDispatcher->waitForIdle();
4821
4822 // System key is not passed down
4823 window->assertNoEvents();
4824
4825 // Should have poked user activity
4826 mFakePolicy->assertUserActivityPoked();
4827}
4828
4829TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4832 "Fake Window", ADISPLAY_ID_DEFAULT);
4833
4834 window->setFocusable(true);
4835 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4836 setFocusedWindow(window);
4837
4838 window->consumeFocusEvent(true);
4839
4840 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4841 mDispatcher->waitForIdle();
4842
4843 // System key is not passed down
4844 window->assertNoEvents();
4845
4846 // Should have poked user activity
4847 mFakePolicy->assertUserActivityPoked();
4848}
4849
4850TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4852 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4853 "Fake Window", ADISPLAY_ID_DEFAULT);
4854
4855 window->setDisableUserActivity(true);
4856 window->setFocusable(true);
4857 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4858 setFocusedWindow(window);
4859
4860 window->consumeFocusEvent(true);
4861
4862 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4863 mDispatcher->waitForIdle();
4864
4865 // System key is not passed down
4866 window->assertNoEvents();
4867
4868 // Should have poked user activity
4869 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004870}
4871
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004872TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4875 "Fake Window", ADISPLAY_ID_DEFAULT);
4876
4877 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4878
4879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4880 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4881 ADISPLAY_ID_DEFAULT, {100, 100}))
4882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4883
4884 window->consumeMotionEvent(
4885 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4886
4887 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004888 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004889 mFakePolicy->assertUserActivityPoked();
4890}
4891
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004892TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004894 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4895 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004896
Arthur Hung72d8dc32020-03-28 00:48:39 +00004897 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004898
Prabir Pradhan678438e2023-04-13 19:32:51 +00004899 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004900 mDispatcher->waitForIdle();
4901
4902 window->assertNoEvents();
4903}
4904
4905// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4906TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004908 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4909 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004910
Arthur Hung72d8dc32020-03-28 00:48:39 +00004911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004912
4913 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004914 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004915 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004916 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4917 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004918
4919 // Window should receive only the motion event
4920 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4921 window->assertNoEvents(); // Key event or focus event will not be received
4922}
4923
arthurhungea3f4fc2020-12-21 23:18:53 +08004924TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4926
arthurhungea3f4fc2020-12-21 23:18:53 +08004927 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004928 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4929 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004930 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004931
arthurhungea3f4fc2020-12-21 23:18:53 +08004932 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004933 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4934 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004935 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004936
4937 // Add the windows to the dispatcher
4938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4939
4940 PointF pointInFirst = {300, 200};
4941 PointF pointInSecond = {300, 600};
4942
4943 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004944 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4945 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4946 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004947 // Only the first window should get the down event
4948 firstWindow->consumeMotionDown();
4949 secondWindow->assertNoEvents();
4950
4951 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004952 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4953 ADISPLAY_ID_DEFAULT,
4954 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004955 // The first window gets a move and the second a down
4956 firstWindow->consumeMotionMove();
4957 secondWindow->consumeMotionDown();
4958
4959 // Send pointer cancel to the second window
4960 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004961 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004962 {pointInFirst, pointInSecond});
4963 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004964 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004965 // The first window gets move and the second gets cancel.
4966 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4967 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4968
4969 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4971 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004972 // The first window gets up and the second gets nothing.
4973 firstWindow->consumeMotionUp();
4974 secondWindow->assertNoEvents();
4975}
4976
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004977TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4978 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4979
4980 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004981 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004982 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4983 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4984 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4985 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4986
Harry Cutts33476232023-01-30 19:57:29 +00004987 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004988 window->assertNoEvents();
4989 mDispatcher->waitForIdle();
4990}
4991
chaviwd1c23182019-12-20 18:44:56 -08004992class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004993public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004994 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004995 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004996 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004997 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004998 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004999 }
5000
chaviwd1c23182019-12-20 18:44:56 -08005001 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
5002
5003 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005004 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
5005 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08005006 }
5007
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07005008 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
5009
5010 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
5011
chaviwd1c23182019-12-20 18:44:56 -08005012 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005013 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08005014 expectedDisplayId, expectedFlags);
5015 }
5016
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005017 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005018 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005019 expectedDisplayId, expectedFlags);
5020 }
5021
chaviwd1c23182019-12-20 18:44:56 -08005022 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005023 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08005024 expectedDisplayId, expectedFlags);
5025 }
5026
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005027 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005028 mInputReceiver->consumeMotionEvent(
5029 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
5030 WithDisplayId(expectedDisplayId),
5031 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005032 }
5033
Arthur Hungfbfa5722021-11-16 02:45:54 +00005034 void consumeMotionPointerDown(int32_t pointerIdx) {
5035 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
5036 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005037 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005038 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00005039 }
5040
Evan Rosky84f07f02021-04-16 10:42:42 -07005041 MotionEvent* consumeMotion() {
5042 InputEvent* event = mInputReceiver->consume();
5043 if (!event) {
5044 ADD_FAILURE() << "No event was produced";
5045 return nullptr;
5046 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005047 if (event->getType() != InputEventType::MOTION) {
5048 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07005049 return nullptr;
5050 }
5051 return static_cast<MotionEvent*>(event);
5052 }
5053
chaviwd1c23182019-12-20 18:44:56 -08005054 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
5055
5056private:
5057 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00005058};
5059
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005060using InputDispatcherMonitorTest = InputDispatcherTest;
5061
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005062/**
5063 * Two entities that receive touch: A window, and a global monitor.
5064 * The touch goes to the window, and then the window disappears.
5065 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5066 * for the monitor, as well.
5067 * 1. foregroundWindow
5068 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5069 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005070TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5072 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005073 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005074
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005075 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005076
5077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5079 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5080 {100, 200}))
5081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5082
5083 // Both the foreground window and the global monitor should receive the touch down
5084 window->consumeMotionDown();
5085 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5086
5087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5088 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5089 ADISPLAY_ID_DEFAULT, {110, 200}))
5090 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5091
5092 window->consumeMotionMove();
5093 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5094
5095 // Now the foreground window goes away
5096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5097 window->consumeMotionCancel();
5098 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5099
5100 // If more events come in, there will be no more foreground window to send them to. This will
5101 // cause a cancel for the monitor, as well.
5102 ASSERT_EQ(InputEventInjectionResult::FAILED,
5103 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5104 ADISPLAY_ID_DEFAULT, {120, 200}))
5105 << "Injection should fail because the window was removed";
5106 window->assertNoEvents();
5107 // Global monitor now gets the cancel
5108 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5109}
5110
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005111TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005112 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005113 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5114 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005115 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005116
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005117 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005118
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005120 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005122 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005123 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005124}
5125
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005126TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5127 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005128
Chris Yea209fde2020-07-22 13:54:51 -07005129 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005130 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5131 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005132 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005133
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005135 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005137 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005138 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005139
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005140 // Pilfer pointers from the monitor.
5141 // This should not do anything and the window should continue to receive events.
5142 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005143
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005145 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5146 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005148
5149 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5150 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005151}
5152
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005153TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005155 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5156 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005157 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5158 window->setWindowOffset(20, 40);
5159 window->setWindowTransform(0, 1, -1, 0);
5160
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005161 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005162
5163 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5164 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5165 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5166 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5167 MotionEvent* event = monitor.consumeMotion();
5168 // Even though window has transform, gesture monitor must not.
5169 ASSERT_EQ(ui::Transform(), event->getTransform());
5170}
5171
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005172TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005174 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005175
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005176 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005177 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005178 << "Injection should fail if there is a monitor, but no touchable window";
5179 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005180}
5181
chaviw81e2bb92019-12-18 15:03:51 -08005182TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005184 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5185 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005186
Arthur Hung72d8dc32020-03-28 00:48:39 +00005187 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005188
5189 NotifyMotionArgs motionArgs =
5190 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5191 ADISPLAY_ID_DEFAULT);
5192
Prabir Pradhan678438e2023-04-13 19:32:51 +00005193 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005194 // Window should receive motion down event.
5195 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5196
5197 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005198 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005199 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5200 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5201 motionArgs.pointerCoords[0].getX() - 10);
5202
Prabir Pradhan678438e2023-04-13 19:32:51 +00005203 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005204 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005205 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005206}
5207
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005208/**
5209 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5210 * the device default right away. In the test scenario, we check both the default value,
5211 * and the action of enabling / disabling.
5212 */
5213TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005215 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5216 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005217 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005218
5219 // Set focused application.
5220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005221 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005222
5223 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005224 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005225 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005226 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005227
5228 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005229 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005230 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005231 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005232
5233 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005234 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005235 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005236 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005237 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005239 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005240 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005241
5242 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005243 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005244 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005245 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005246
5247 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005248 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005249 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005250 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005251 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005252 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005253 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005254 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005255
5256 window->assertNoEvents();
5257}
5258
Gang Wange9087892020-01-07 12:17:14 -05005259TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005261 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5262 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005263
5264 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005265 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005266
Arthur Hung72d8dc32020-03-28 00:48:39 +00005267 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005268 setFocusedWindow(window);
5269
Harry Cutts33476232023-01-30 19:57:29 +00005270 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005271
Prabir Pradhan678438e2023-04-13 19:32:51 +00005272 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5273 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005274
5275 InputEvent* event = window->consume();
5276 ASSERT_NE(event, nullptr);
5277
5278 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5279 ASSERT_NE(verified, nullptr);
5280 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5281
5282 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5283 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5284 ASSERT_EQ(keyArgs.source, verified->source);
5285 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5286
5287 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5288
5289 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005290 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005291 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005292 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5293 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5294 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5295 ASSERT_EQ(0, verifiedKey.repeatCount);
5296}
5297
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005298TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005300 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5301 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005302
5303 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5304
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005305 ui::Transform transform;
5306 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5307
5308 gui::DisplayInfo displayInfo;
5309 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5310 displayInfo.transform = transform;
5311
Patrick Williamsd828f302023-04-28 17:52:08 -05005312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005313
Prabir Pradhan678438e2023-04-13 19:32:51 +00005314 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005315 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5316 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005317 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005318
5319 InputEvent* event = window->consume();
5320 ASSERT_NE(event, nullptr);
5321
5322 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5323 ASSERT_NE(verified, nullptr);
5324 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5325
5326 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5327 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5328 EXPECT_EQ(motionArgs.source, verified->source);
5329 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5330
5331 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5332
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005333 const vec2 rawXY =
5334 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5335 motionArgs.pointerCoords[0].getXYValue());
5336 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5337 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005338 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005339 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005340 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005341 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5342 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5343}
5344
chaviw09c8d2d2020-08-24 15:48:26 -07005345/**
5346 * Ensure that separate calls to sign the same data are generating the same key.
5347 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5348 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5349 * tests.
5350 */
5351TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5352 KeyEvent event = getTestKeyEvent();
5353 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5354
5355 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5356 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5357 ASSERT_EQ(hmac1, hmac2);
5358}
5359
5360/**
5361 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5362 */
5363TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5364 KeyEvent event = getTestKeyEvent();
5365 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5366 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5367
5368 verifiedEvent.deviceId += 1;
5369 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5370
5371 verifiedEvent.source += 1;
5372 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5373
5374 verifiedEvent.eventTimeNanos += 1;
5375 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5376
5377 verifiedEvent.displayId += 1;
5378 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5379
5380 verifiedEvent.action += 1;
5381 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5382
5383 verifiedEvent.downTimeNanos += 1;
5384 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5385
5386 verifiedEvent.flags += 1;
5387 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5388
5389 verifiedEvent.keyCode += 1;
5390 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5391
5392 verifiedEvent.scanCode += 1;
5393 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5394
5395 verifiedEvent.metaState += 1;
5396 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5397
5398 verifiedEvent.repeatCount += 1;
5399 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5400}
5401
Vishnu Nair958da932020-08-21 17:12:37 -07005402TEST_F(InputDispatcherTest, SetFocusedWindow) {
5403 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5404 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005405 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005406 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005407 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005408 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5409
5410 // Top window is also focusable but is not granted focus.
5411 windowTop->setFocusable(true);
5412 windowSecond->setFocusable(true);
5413 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5414 setFocusedWindow(windowSecond);
5415
5416 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005419
5420 // Focused window should receive event.
5421 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5422 windowTop->assertNoEvents();
5423}
5424
5425TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5427 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005428 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005429 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5430
5431 window->setFocusable(true);
5432 // Release channel for window is no longer valid.
5433 window->releaseChannel();
5434 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5435 setFocusedWindow(window);
5436
5437 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005438 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5439 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005440
5441 // window channel is invalid, so it should not receive any input event.
5442 window->assertNoEvents();
5443}
5444
5445TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5447 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005448 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005449 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5451
Vishnu Nair958da932020-08-21 17:12:37 -07005452 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5453 setFocusedWindow(window);
5454
5455 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005456 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5457 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005458
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005459 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005460 window->assertNoEvents();
5461}
5462
5463TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5465 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005466 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005467 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005468 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005469 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5470
5471 windowTop->setFocusable(true);
5472 windowSecond->setFocusable(true);
5473 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5474 setFocusedWindow(windowTop);
5475 windowTop->consumeFocusEvent(true);
5476
Chavi Weingarten847e8512023-03-29 00:26:09 +00005477 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5478 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005479 windowSecond->consumeFocusEvent(true);
5480 windowTop->consumeFocusEvent(false);
5481
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5483 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005484
5485 // Focused window should receive event.
5486 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5487}
5488
Chavi Weingarten847e8512023-03-29 00:26:09 +00005489TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5491 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005493 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005494 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005495 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5496
5497 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005498 windowSecond->setFocusable(false);
5499 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005500 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005501 setFocusedWindow(windowTop);
5502 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005503
Chavi Weingarten847e8512023-03-29 00:26:09 +00005504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5505 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005506
5507 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005508 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005509 windowSecond->assertNoEvents();
5510}
5511
5512TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5513 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5514 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005515 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005516 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005517 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5518 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005519 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5520
5521 window->setFocusable(true);
5522 previousFocusedWindow->setFocusable(true);
5523 window->setVisible(false);
5524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5525 setFocusedWindow(previousFocusedWindow);
5526 previousFocusedWindow->consumeFocusEvent(true);
5527
5528 // Requesting focus on invisible window takes focus from currently focused window.
5529 setFocusedWindow(window);
5530 previousFocusedWindow->consumeFocusEvent(false);
5531
5532 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005534 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5535 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005536
5537 // Window does not get focus event or key down.
5538 window->assertNoEvents();
5539
5540 // Window becomes visible.
5541 window->setVisible(true);
5542 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5543
5544 // Window receives focus event.
5545 window->consumeFocusEvent(true);
5546 // Focused window receives key down.
5547 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5548}
5549
Vishnu Nair599f1412021-06-21 10:39:58 -07005550TEST_F(InputDispatcherTest, DisplayRemoved) {
5551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5552 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005553 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005554 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5555
5556 // window is granted focus.
5557 window->setFocusable(true);
5558 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5559 setFocusedWindow(window);
5560 window->consumeFocusEvent(true);
5561
5562 // When a display is removed window loses focus.
5563 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5564 window->consumeFocusEvent(false);
5565}
5566
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005567/**
5568 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5569 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5570 * of the 'slipperyEnterWindow'.
5571 *
5572 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5573 * a way so that the touched location is no longer covered by the top window.
5574 *
5575 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5576 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5577 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5578 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5579 * with ACTION_DOWN).
5580 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5581 * window moved itself away from the touched location and had Flag::SLIPPERY.
5582 *
5583 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5584 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5585 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5586 *
5587 * In this test, we ensure that the event received by the bottom window has
5588 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5589 */
5590TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005591 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005592 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005593
5594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5595 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5596
5597 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005598 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005599 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005600 // Make sure this one overlaps the bottom window
5601 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5602 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5603 // one. Windows with the same owner are not considered to be occluding each other.
5604 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5605
5606 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005607 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005608 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5609
5610 mDispatcher->setInputWindows(
5611 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5612
5613 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005614 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5615 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5616 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005617 slipperyExitWindow->consumeMotionDown();
5618 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5619 mDispatcher->setInputWindows(
5620 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5621
Prabir Pradhan678438e2023-04-13 19:32:51 +00005622 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5623 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5624 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005625
5626 slipperyExitWindow->consumeMotionCancel();
5627
5628 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5629 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5630}
5631
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005632/**
5633 * Two windows, one on the left and another on the right. The left window is slippery. The right
5634 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5635 * touch moves from the left window into the right window, the gesture should continue to go to the
5636 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5637 * reproduces a crash.
5638 */
5639TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5641
5642 sp<FakeWindowHandle> leftSlipperyWindow =
5643 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5644 leftSlipperyWindow->setSlippery(true);
5645 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5646
5647 sp<FakeWindowHandle> rightDropTouchesWindow =
5648 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5649 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5650 rightDropTouchesWindow->setDropInput(true);
5651
5652 mDispatcher->setInputWindows(
5653 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5654
5655 // Start touch in the left window
5656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5657 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5658 .build());
5659 leftSlipperyWindow->consumeMotionDown();
5660
5661 // And move it into the right window
5662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5663 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5664 .build());
5665
5666 // Since the right window isn't eligible to receive input, touch does not slip.
5667 // The left window continues to receive the gesture.
5668 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5669 rightDropTouchesWindow->assertNoEvents();
5670}
5671
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005672TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005673 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5675
5676 sp<FakeWindowHandle> leftWindow =
5677 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5678 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005679 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005680
5681 sp<FakeWindowHandle> rightSpy =
5682 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5683 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005684 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005685 rightSpy->setSpy(true);
5686 rightSpy->setTrustedOverlay(true);
5687
5688 sp<FakeWindowHandle> rightWindow =
5689 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5690 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005691 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005692
5693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5694
5695 // Touch in the left window
5696 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5697 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5698 .build());
5699 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5700 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005701 ASSERT_NO_FATAL_FAILURE(
5702 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005703
5704 // Touch another finger over the right windows
5705 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5706 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5707 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5708 .build());
5709 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5710 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5711 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5712 mDispatcher->waitForIdle();
5713 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005714 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5715 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005716
5717 // Release finger over left window. The UP actions are not treated as device interaction.
5718 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5719 // is part of the UP action, we do not treat this as device interaction.
5720 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5721 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5722 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5723 .build());
5724 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5725 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5726 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5727 mDispatcher->waitForIdle();
5728 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5729
5730 // Move remaining finger
5731 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5732 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5733 .build());
5734 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5735 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5736 mDispatcher->waitForIdle();
5737 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005738 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005739
5740 // Release all fingers
5741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5742 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5743 .build());
5744 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5745 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5746 mDispatcher->waitForIdle();
5747 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5748}
5749
5750TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5752
5753 sp<FakeWindowHandle> window =
5754 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5755 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00005756 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005757
5758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5759 setFocusedWindow(window);
5760 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5761
5762 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5763 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5764 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005765 ASSERT_NO_FATAL_FAILURE(
5766 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005767
5768 // The UP actions are not treated as device interaction.
5769 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5770 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5771 mDispatcher->waitForIdle();
5772 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5773}
5774
Garfield Tan1c7bc862020-01-28 13:24:04 -08005775class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5776protected:
5777 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5778 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5779
Chris Yea209fde2020-07-22 13:54:51 -07005780 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005781 sp<FakeWindowHandle> mWindow;
5782
5783 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005784 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005785 mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Prabir Pradhana41d2442023-04-20 21:30:40 +00005786 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Prabir Pradhan87112a72023-04-20 19:13:39 +00005787 mDispatcher->requestRefreshConfiguration();
Garfield Tan1c7bc862020-01-28 13:24:04 -08005788 mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
5789 ASSERT_EQ(OK, mDispatcher->start());
5790
5791 setUpWindow();
5792 }
5793
5794 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005795 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005796 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005797
Vishnu Nair47074b82020-08-14 11:54:47 -07005798 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005800 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005801 mWindow->consumeFocusEvent(true);
5802 }
5803
Chris Ye2ad95392020-09-01 13:44:44 -07005804 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005805 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005806 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005807 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005808 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005809
5810 // Window should receive key down event.
5811 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5812 }
5813
5814 void expectKeyRepeatOnce(int32_t repeatCount) {
5815 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5816 InputEvent* repeatEvent = mWindow->consume();
5817 ASSERT_NE(nullptr, repeatEvent);
5818
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005819 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005820
5821 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5822 uint32_t eventAction = repeatKeyEvent->getAction();
5823 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5824 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5825 }
5826
Chris Ye2ad95392020-09-01 13:44:44 -07005827 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005828 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005829 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005830 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005831 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005832
5833 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005834 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005835 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005836 }
5837};
5838
5839TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005840 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005841 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5842 expectKeyRepeatOnce(repeatCount);
5843 }
5844}
5845
5846TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005847 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005848 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5849 expectKeyRepeatOnce(repeatCount);
5850 }
Harry Cutts33476232023-01-30 19:57:29 +00005851 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005852 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005853 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5854 expectKeyRepeatOnce(repeatCount);
5855 }
5856}
5857
5858TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005859 sendAndConsumeKeyDown(/*deviceId=*/1);
5860 expectKeyRepeatOnce(/*repeatCount=*/1);
5861 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005862 mWindow->assertNoEvents();
5863}
5864
5865TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005866 sendAndConsumeKeyDown(/*deviceId=*/1);
5867 expectKeyRepeatOnce(/*repeatCount=*/1);
5868 sendAndConsumeKeyDown(/*deviceId=*/2);
5869 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005870 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005871 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005872 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005873 expectKeyRepeatOnce(/*repeatCount=*/2);
5874 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005875 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005876 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005877 mWindow->assertNoEvents();
5878}
5879
5880TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005881 sendAndConsumeKeyDown(/*deviceId=*/1);
5882 expectKeyRepeatOnce(/*repeatCount=*/1);
5883 sendAndConsumeKeyDown(/*deviceId=*/2);
5884 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005885 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005886 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005887 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005888 mWindow->assertNoEvents();
5889}
5890
liushenxiang42232912021-05-21 20:24:09 +08005891TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5892 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005893 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005894 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005895 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5896 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5897 mWindow->assertNoEvents();
5898}
5899
Garfield Tan1c7bc862020-01-28 13:24:04 -08005900TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005901 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005902 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005903 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5904 InputEvent* repeatEvent = mWindow->consume();
5905 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5906 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5907 IdGenerator::getSource(repeatEvent->getId()));
5908 }
5909}
5910
5911TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005912 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005913 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005914
5915 std::unordered_set<int32_t> idSet;
5916 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5917 InputEvent* repeatEvent = mWindow->consume();
5918 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5919 int32_t id = repeatEvent->getId();
5920 EXPECT_EQ(idSet.end(), idSet.find(id));
5921 idSet.insert(id);
5922 }
5923}
5924
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005925/* Test InputDispatcher for MultiDisplay */
5926class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5927public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005928 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005929 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005930
Chris Yea209fde2020-07-22 13:54:51 -07005931 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005932 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005933 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005934
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005935 // Set focus window for primary display, but focused display would be second one.
5936 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005937 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005938 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005939 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005940 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005941
Chris Yea209fde2020-07-22 13:54:51 -07005942 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005943 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005944 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005945 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005946 // Set focus display to second one.
5947 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5948 // Set focus window for second display.
5949 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005950 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005951 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005952 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005953 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005954 }
5955
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005956 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005957 InputDispatcherTest::TearDown();
5958
Chris Yea209fde2020-07-22 13:54:51 -07005959 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005960 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005961 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005962 windowInSecondary.clear();
5963 }
5964
5965protected:
Chris Yea209fde2020-07-22 13:54:51 -07005966 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005967 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005968 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005969 sp<FakeWindowHandle> windowInSecondary;
5970};
5971
5972TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5973 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5975 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005977 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005978 windowInSecondary->assertNoEvents();
5979
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005980 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5982 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005984 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005985 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005986}
5987
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005988TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005989 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5991 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005992 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005993 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005994 windowInSecondary->assertNoEvents();
5995
5996 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005997 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005998 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005999 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006000 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08006001
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006002 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006003 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08006004
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006005 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006006 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006007 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08006008
6009 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006010 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006011 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08006012 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006013 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08006014 windowInSecondary->assertNoEvents();
6015}
6016
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006017// Test per-display input monitors for motion event.
6018TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08006019 FakeMonitorReceiver monitorInPrimary =
6020 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6021 FakeMonitorReceiver monitorInSecondary =
6022 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006023
6024 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6026 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006028 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006029 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006030 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006031 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006032
6033 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6035 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006037 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006038 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006039 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08006040 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006041
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08006042 // Lift up the touch from the second display
6043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6044 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6045 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6046 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
6047 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
6048
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006049 // Test inject a non-pointer motion event.
6050 // If specific a display, it will dispatch to the focused window of particular display,
6051 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6053 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
6054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006055 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006056 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006057 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006058 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006059}
6060
6061// Test per-display input monitors for key event.
6062TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006063 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08006064 FakeMonitorReceiver monitorInPrimary =
6065 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6066 FakeMonitorReceiver monitorInSecondary =
6067 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006068
6069 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
6071 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006072 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08006073 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08006074 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08006075 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08006076}
6077
Vishnu Nair958da932020-08-21 17:12:37 -07006078TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6079 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006080 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006081 secondWindowInPrimary->setFocusable(true);
6082 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6083 setFocusedWindow(secondWindowInPrimary);
6084 windowInPrimary->consumeFocusEvent(false);
6085 secondWindowInPrimary->consumeFocusEvent(true);
6086
6087 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6089 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006090 windowInPrimary->assertNoEvents();
6091 windowInSecondary->assertNoEvents();
6092 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6093}
6094
Arthur Hungdfd528e2021-12-08 13:23:04 +00006095TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6096 FakeMonitorReceiver monitorInPrimary =
6097 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6098 FakeMonitorReceiver monitorInSecondary =
6099 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6100
6101 // Test touch down on primary display.
6102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6103 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6105 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6106 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6107
6108 // Test touch down on second display.
6109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6110 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6111 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6112 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6113 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6114
6115 // Trigger cancel touch.
6116 mDispatcher->cancelCurrentTouch();
6117 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6118 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6119 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6120 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6121
6122 // Test inject a move motion event, no window/monitor should receive the event.
6123 ASSERT_EQ(InputEventInjectionResult::FAILED,
6124 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6125 ADISPLAY_ID_DEFAULT, {110, 200}))
6126 << "Inject motion event should return InputEventInjectionResult::FAILED";
6127 windowInPrimary->assertNoEvents();
6128 monitorInPrimary.assertNoEvents();
6129
6130 ASSERT_EQ(InputEventInjectionResult::FAILED,
6131 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6132 SECOND_DISPLAY_ID, {110, 200}))
6133 << "Inject motion event should return InputEventInjectionResult::FAILED";
6134 windowInSecondary->assertNoEvents();
6135 monitorInSecondary.assertNoEvents();
6136}
6137
Jackal Guof9696682018-10-05 12:23:23 +08006138class InputFilterTest : public InputDispatcherTest {
6139protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006140 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6141 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006142 NotifyMotionArgs motionArgs;
6143
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006144 motionArgs =
6145 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006146 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006147 motionArgs =
6148 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006149 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006150 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006151 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006152 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006153 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006154 } else {
6155 mFakePolicy->assertFilterInputEventWasNotCalled();
6156 }
6157 }
6158
6159 void testNotifyKey(bool expectToBeFiltered) {
6160 NotifyKeyArgs keyArgs;
6161
6162 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006163 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006164 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006165 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006166 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006167
6168 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006169 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006170 } else {
6171 mFakePolicy->assertFilterInputEventWasNotCalled();
6172 }
6173 }
6174};
6175
6176// Test InputFilter for MotionEvent
6177TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6178 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
6179 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6180 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6181
6182 // Enable InputFilter
6183 mDispatcher->setInputFilterEnabled(true);
6184 // Test touch on both primary and second display, and check if both events are filtered.
6185 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true);
6186 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true);
6187
6188 // Disable InputFilter
6189 mDispatcher->setInputFilterEnabled(false);
6190 // Test touch on both primary and second display, and check if both events aren't filtered.
6191 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ false);
6192 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ false);
6193}
6194
6195// Test InputFilter for KeyEvent
6196TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6197 // Since the InputFilter is disabled by default, check if key event aren't filtered.
6198 testNotifyKey(/*expectToBeFiltered*/ false);
6199
6200 // Enable InputFilter
6201 mDispatcher->setInputFilterEnabled(true);
6202 // Send a key event, and check if it is filtered.
6203 testNotifyKey(/*expectToBeFiltered*/ true);
6204
6205 // Disable InputFilter
6206 mDispatcher->setInputFilterEnabled(false);
6207 // Send a key event, and check if it isn't filtered.
6208 testNotifyKey(/*expectToBeFiltered*/ false);
6209}
6210
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006211// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6212// logical display coordinate space.
6213TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6214 ui::Transform firstDisplayTransform;
6215 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6216 ui::Transform secondDisplayTransform;
6217 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6218
6219 std::vector<gui::DisplayInfo> displayInfos(2);
6220 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6221 displayInfos[0].transform = firstDisplayTransform;
6222 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6223 displayInfos[1].transform = secondDisplayTransform;
6224
Patrick Williamsd828f302023-04-28 17:52:08 -05006225 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006226
6227 // Enable InputFilter
6228 mDispatcher->setInputFilterEnabled(true);
6229
6230 // Ensure the correct transforms are used for the displays.
6231 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered*/ true, firstDisplayTransform);
6232 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered*/ true, secondDisplayTransform);
6233}
6234
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006235class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6236protected:
6237 virtual void SetUp() override {
6238 InputDispatcherTest::SetUp();
6239
6240 /**
6241 * We don't need to enable input filter to test the injected event policy, but we enabled it
6242 * here to make the tests more realistic, since this policy only matters when inputfilter is
6243 * on.
6244 */
6245 mDispatcher->setInputFilterEnabled(true);
6246
6247 std::shared_ptr<InputApplicationHandle> application =
6248 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006249 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6250 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006251
6252 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6253 mWindow->setFocusable(true);
6254 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6255 setFocusedWindow(mWindow);
6256 mWindow->consumeFocusEvent(true);
6257 }
6258
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006259 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6260 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006261 KeyEvent event;
6262
6263 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6264 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6265 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006266 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006267 const int32_t additionalPolicyFlags =
6268 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006270 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006271 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6272 policyFlags | additionalPolicyFlags));
6273
6274 InputEvent* received = mWindow->consume();
6275 ASSERT_NE(nullptr, received);
6276 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006277 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006278 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6279 ASSERT_EQ(flags, keyEvent.getFlags());
6280 }
6281
6282 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6283 int32_t flags) {
6284 MotionEvent event;
6285 PointerProperties pointerProperties[1];
6286 PointerCoords pointerCoords[1];
6287 pointerProperties[0].clear();
6288 pointerProperties[0].id = 0;
6289 pointerCoords[0].clear();
6290 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6291 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6292
6293 ui::Transform identityTransform;
6294 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6295 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6296 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6297 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6298 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006299 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006300 eventTime,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006301 /*pointerCount*/ 1, pointerProperties, pointerCoords);
6302
6303 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006305 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006306 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
6307 policyFlags | additionalPolicyFlags));
6308
6309 InputEvent* received = mWindow->consume();
6310 ASSERT_NE(nullptr, received);
6311 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006312 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006313 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6314 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006315 }
6316
6317private:
6318 sp<FakeWindowHandle> mWindow;
6319};
6320
6321TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006322 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6323 // filter. Without it, the event will no different from a regularly injected event, and the
6324 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006325 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6326 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006327}
6328
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006329TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006330 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006331 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006332 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6333}
6334
6335TEST_F(InputFilterInjectionPolicyTest,
6336 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6337 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006338 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006339 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006340}
6341
6342TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006343 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6344 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006345}
6346
chaviwfd6d3512019-03-25 13:23:49 -07006347class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006348 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006349 InputDispatcherTest::SetUp();
6350
Chris Yea209fde2020-07-22 13:54:51 -07006351 std::shared_ptr<FakeApplicationHandle> application =
6352 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006353 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006354 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006355 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006356
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006357 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006358 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006359 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006360
6361 // Set focused application.
6362 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006363 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006364
6365 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006366 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006367 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006368 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006369 }
6370
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006371 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006372 InputDispatcherTest::TearDown();
6373
6374 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006375 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006376 }
6377
6378protected:
6379 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006380 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006381 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006382};
6383
6384// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6385// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6386// the onPointerDownOutsideFocus callback.
6387TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006389 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6390 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006392 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006393
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006394 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006395 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6396}
6397
6398// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6399// DOWN on the window that doesn't have focus. Ensure no window received the
6400// onPointerDownOutsideFocus callback.
6401TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006403 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006405 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006406
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006407 ASSERT_TRUE(mDispatcher->waitForIdle());
6408 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006409}
6410
6411// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6412// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6413TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6415 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006416 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006417 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006418
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006419 ASSERT_TRUE(mDispatcher->waitForIdle());
6420 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006421}
6422
6423// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6424// DOWN on the window that already has focus. Ensure no window received the
6425// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006426TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006428 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006429 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006431 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006432
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006433 ASSERT_TRUE(mDispatcher->waitForIdle());
6434 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006435}
6436
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006437// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6438// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6439TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6440 const MotionEvent event =
6441 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6442 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006443 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006444 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6445 .build();
6446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6447 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6448 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6449
6450 ASSERT_TRUE(mDispatcher->waitForIdle());
6451 mFakePolicy->assertOnPointerDownWasNotCalled();
6452 // Ensure that the unfocused window did not receive any FOCUS events.
6453 mUnfocusedWindow->assertNoEvents();
6454}
6455
chaviwaf87b3e2019-10-01 16:59:28 -07006456// These tests ensures we can send touch events to a single client when there are multiple input
6457// windows that point to the same client token.
6458class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6459 virtual void SetUp() override {
6460 InputDispatcherTest::SetUp();
6461
Chris Yea209fde2020-07-22 13:54:51 -07006462 std::shared_ptr<FakeApplicationHandle> application =
6463 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006464 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6465 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006466 mWindow1->setFrame(Rect(0, 0, 100, 100));
6467
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006468 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6469 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006470 mWindow2->setFrame(Rect(100, 100, 200, 200));
6471
Arthur Hung72d8dc32020-03-28 00:48:39 +00006472 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006473 }
6474
6475protected:
6476 sp<FakeWindowHandle> mWindow1;
6477 sp<FakeWindowHandle> mWindow2;
6478
6479 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006480 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006481 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6482 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006483 }
6484
6485 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6486 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006487 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006488 InputEvent* event = window->consume();
6489
6490 ASSERT_NE(nullptr, event) << name.c_str()
6491 << ": consumer should have returned non-NULL event.";
6492
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006493 ASSERT_EQ(InputEventType::MOTION, event->getType())
6494 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006495
6496 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006497 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006498 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006499
6500 for (size_t i = 0; i < points.size(); i++) {
6501 float expectedX = points[i].x;
6502 float expectedY = points[i].y;
6503
6504 EXPECT_EQ(expectedX, motionEvent.getX(i))
6505 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6506 << ", got " << motionEvent.getX(i);
6507 EXPECT_EQ(expectedY, motionEvent.getY(i))
6508 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6509 << ", got " << motionEvent.getY(i);
6510 }
6511 }
chaviw9eaa22c2020-07-01 16:21:27 -07006512
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006513 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006514 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006515 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6516 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006517
6518 // Always consume from window1 since it's the window that has the InputReceiver
6519 consumeMotionEvent(mWindow1, action, expectedPoints);
6520 }
chaviwaf87b3e2019-10-01 16:59:28 -07006521};
6522
6523TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6524 // Touch Window 1
6525 PointF touchedPoint = {10, 10};
6526 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006527 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006528
6529 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006530 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006531
6532 // Touch Window 2
6533 touchedPoint = {150, 150};
6534 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006535 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006536}
6537
chaviw9eaa22c2020-07-01 16:21:27 -07006538TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6539 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006540 mWindow2->setWindowScale(0.5f, 0.5f);
6541
6542 // Touch Window 1
6543 PointF touchedPoint = {10, 10};
6544 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006545 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006546 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006547 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006548
6549 // Touch Window 2
6550 touchedPoint = {150, 150};
6551 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006552 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6553 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006554
chaviw9eaa22c2020-07-01 16:21:27 -07006555 // Update the transform so rotation is set
6556 mWindow2->setWindowTransform(0, -1, 1, 0);
6557 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6558 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006559}
6560
chaviw9eaa22c2020-07-01 16:21:27 -07006561TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006562 mWindow2->setWindowScale(0.5f, 0.5f);
6563
6564 // Touch Window 1
6565 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6566 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006567 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006568
6569 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006570 touchedPoints.push_back(PointF{150, 150});
6571 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006572 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006573
chaviw9eaa22c2020-07-01 16:21:27 -07006574 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006575 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006576 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006577
chaviw9eaa22c2020-07-01 16:21:27 -07006578 // Update the transform so rotation is set for Window 2
6579 mWindow2->setWindowTransform(0, -1, 1, 0);
6580 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006581 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006582}
6583
chaviw9eaa22c2020-07-01 16:21:27 -07006584TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006585 mWindow2->setWindowScale(0.5f, 0.5f);
6586
6587 // Touch Window 1
6588 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6589 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006590 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006591
6592 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006593 touchedPoints.push_back(PointF{150, 150});
6594 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006595
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006596 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006597
6598 // Move both windows
6599 touchedPoints = {{20, 20}, {175, 175}};
6600 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6601 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6602
chaviw9eaa22c2020-07-01 16:21:27 -07006603 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006604
chaviw9eaa22c2020-07-01 16:21:27 -07006605 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006606 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006607 expectedPoints.pop_back();
6608
6609 // Touch Window 2
6610 mWindow2->setWindowTransform(0, -1, 1, 0);
6611 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006612 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006613
6614 // Move both windows
6615 touchedPoints = {{20, 20}, {175, 175}};
6616 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6617 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6618
6619 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006620}
6621
6622TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6623 mWindow1->setWindowScale(0.5f, 0.5f);
6624
6625 // Touch Window 1
6626 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6627 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006628 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006629
6630 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006631 touchedPoints.push_back(PointF{150, 150});
6632 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006633
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006634 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006635
6636 // Move both windows
6637 touchedPoints = {{20, 20}, {175, 175}};
6638 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6639 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6640
chaviw9eaa22c2020-07-01 16:21:27 -07006641 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006642}
6643
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006644/**
6645 * When one of the windows is slippery, the touch should not slip into the other window with the
6646 * same input channel.
6647 */
6648TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6649 mWindow1->setSlippery(true);
6650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6651
6652 // Touch down in window 1
6653 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6654 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6655 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6656
6657 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6658 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6659 // getting generated.
6660 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6661 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6662
6663 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6664}
6665
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006666/**
6667 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6668 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6669 * that the pointer is hovering over may have a different transform.
6670 */
6671TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6672 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6673
6674 // Start hover in window 1
6675 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6676 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6677 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6678 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6679
6680 // Move hover to window 2.
6681 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6682 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6683
6684 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6685 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6686 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6687}
6688
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006689class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6690 virtual void SetUp() override {
6691 InputDispatcherTest::SetUp();
6692
Chris Yea209fde2020-07-22 13:54:51 -07006693 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006694 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006695 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6696 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006697 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006698 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006699 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006700
6701 // Set focused application.
6702 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6703
6704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006705 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006706 mWindow->consumeFocusEvent(true);
6707 }
6708
6709 virtual void TearDown() override {
6710 InputDispatcherTest::TearDown();
6711 mWindow.clear();
6712 }
6713
6714protected:
Chris Yea209fde2020-07-22 13:54:51 -07006715 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006716 sp<FakeWindowHandle> mWindow;
6717 static constexpr PointF WINDOW_LOCATION = {20, 20};
6718
6719 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006721 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6722 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006724 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6725 WINDOW_LOCATION));
6726 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006727
6728 sp<FakeWindowHandle> addSpyWindow() {
6729 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006730 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006731 spy->setTrustedOverlay(true);
6732 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006733 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006734 spy->setDispatchingTimeout(30ms);
6735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6736 return spy;
6737 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006738};
6739
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006740// Send a tap and respond, which should not cause an ANR.
6741TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6742 tapOnWindow();
6743 mWindow->consumeMotionDown();
6744 mWindow->consumeMotionUp();
6745 ASSERT_TRUE(mDispatcher->waitForIdle());
6746 mFakePolicy->assertNotifyAnrWasNotCalled();
6747}
6748
6749// Send a regular key and respond, which should not cause an ANR.
6750TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006752 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6753 ASSERT_TRUE(mDispatcher->waitForIdle());
6754 mFakePolicy->assertNotifyAnrWasNotCalled();
6755}
6756
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006757TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6758 mWindow->setFocusable(false);
6759 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6760 mWindow->consumeFocusEvent(false);
6761
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006762 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006763 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6764 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6765 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006767 // Key will not go to window because we have no focused window.
6768 // The 'no focused window' ANR timer should start instead.
6769
6770 // Now, the focused application goes away.
6771 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6772 // The key should get dropped and there should be no ANR.
6773
6774 ASSERT_TRUE(mDispatcher->waitForIdle());
6775 mFakePolicy->assertNotifyAnrWasNotCalled();
6776}
6777
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006778// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006779// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6780// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006781TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006783 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6784 WINDOW_LOCATION));
6785
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006786 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6787 ASSERT_TRUE(sequenceNum);
6788 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006789 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006790
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006791 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006792 mWindow->consumeMotionEvent(
6793 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006794 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006795 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006796}
6797
6798// Send a key to the app and have the app not respond right away.
6799TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6800 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006802 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6803 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006804 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006805 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006806 ASSERT_TRUE(mDispatcher->waitForIdle());
6807}
6808
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006809// We have a focused application, but no focused window
6810TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006811 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006812 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6813 mWindow->consumeFocusEvent(false);
6814
6815 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006817 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6818 WINDOW_LOCATION));
6819 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6820 mDispatcher->waitForIdle();
6821 mFakePolicy->assertNotifyAnrWasNotCalled();
6822
6823 // Once a focused event arrives, we get an ANR for this application
6824 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6825 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006826 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006827 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6828 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006829 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006830 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006831 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006832 ASSERT_TRUE(mDispatcher->waitForIdle());
6833}
6834
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006835/**
6836 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6837 * there will not be an ANR.
6838 */
6839TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6840 mWindow->setFocusable(false);
6841 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6842 mWindow->consumeFocusEvent(false);
6843
6844 KeyEvent event;
6845 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6846 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6847
6848 // Define a valid key down event that is stale (too old).
6849 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
6850 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006851 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006852
6853 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6854
6855 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006856 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006857 InputEventInjectionSync::WAIT_FOR_RESULT,
6858 INJECT_EVENT_TIMEOUT, policyFlags);
6859 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6860 << "Injection should fail because the event is stale";
6861
6862 ASSERT_TRUE(mDispatcher->waitForIdle());
6863 mFakePolicy->assertNotifyAnrWasNotCalled();
6864 mWindow->assertNoEvents();
6865}
6866
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006867// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006868// Make sure that we don't notify policy twice about the same ANR.
6869TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006870 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006871 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6872 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006873
6874 // Once a focused event arrives, we get an ANR for this application
6875 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6876 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006877 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006878 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6879 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006880 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006881 const std::chrono::duration appTimeout =
6882 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6883 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006884
Vishnu Naire4df8752022-09-08 09:17:55 -07006885 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006886 // ANR should not be raised again. It is up to policy to do that if it desires.
6887 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006889 // If we now get a focused window, the ANR should stop, but the policy handles that via
6890 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006891 ASSERT_TRUE(mDispatcher->waitForIdle());
6892}
6893
6894// We have a focused application, but no focused window
6895TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006896 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6898 mWindow->consumeFocusEvent(false);
6899
6900 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006901 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006902 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006903 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6904 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905
Vishnu Naire4df8752022-09-08 09:17:55 -07006906 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6907 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006908
6909 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006910 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911 ASSERT_TRUE(mDispatcher->waitForIdle());
6912 mWindow->assertNoEvents();
6913}
6914
6915/**
6916 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6917 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6918 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6919 * the ANR mechanism should still work.
6920 *
6921 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6922 * DOWN event, while not responding on the second one.
6923 */
6924TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6925 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6926 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6927 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6928 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6929 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006930 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006931
6932 // Now send ACTION_UP, with identical timestamp
6933 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6934 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6935 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6936 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006937 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006938
6939 // We have now sent down and up. Let's consume first event and then ANR on the second.
6940 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6941 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006942 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006943}
6944
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006945// A spy window can receive an ANR
6946TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6947 sp<FakeWindowHandle> spy = addSpyWindow();
6948
6949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6950 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6951 WINDOW_LOCATION));
6952 mWindow->consumeMotionDown();
6953
6954 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6955 ASSERT_TRUE(sequenceNum);
6956 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006957 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006958
6959 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006960 spy->consumeMotionEvent(
6961 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006962 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006963 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006964}
6965
6966// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006967// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006968TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6969 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006970
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6972 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006973 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006975
6976 // Stuck on the ACTION_UP
6977 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006978 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006979
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006980 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006981 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006982 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6983 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006984
6985 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6986 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006987 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006988 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006989 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006990}
6991
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006992// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006993// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006994TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6995 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006996
6997 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006998 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6999 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000
7001 mWindow->consumeMotionDown();
7002 // Stuck on the ACTION_UP
7003 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007004 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007005
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007006 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007007 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007008 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7009 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007010
7011 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
7012 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007013 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007014 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007015 spy->assertNoEvents();
7016}
7017
7018TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
7019 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
7020
7021 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
7022
7023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7024 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7025 WINDOW_LOCATION));
7026
7027 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7028 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
7029 ASSERT_TRUE(consumeSeq);
7030
Prabir Pradhanedd96402022-02-15 01:46:16 -08007031 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007032
7033 monitor.finishEvent(*consumeSeq);
7034 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7035
7036 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007037 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007038}
7039
7040// If a window is unresponsive, then you get anr. if the window later catches up and starts to
7041// process events, you don't get an anr. When the window later becomes unresponsive again, you
7042// get an ANR again.
7043// 1. tap -> block on ACTION_UP -> receive ANR
7044// 2. consume all pending events (= queue becomes healthy again)
7045// 3. tap again -> block on ACTION_UP again -> receive ANR second time
7046TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
7047 tapOnWindow();
7048
7049 mWindow->consumeMotionDown();
7050 // Block on ACTION_UP
7051 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007052 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007053 mWindow->consumeMotionUp(); // Now the connection should be healthy again
7054 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007055 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007056 mWindow->assertNoEvents();
7057
7058 tapOnWindow();
7059 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007060 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007061 mWindow->consumeMotionUp();
7062
7063 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007064 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007065 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007066 mWindow->assertNoEvents();
7067}
7068
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007069// If a connection remains unresponsive for a while, make sure policy is only notified once about
7070// it.
7071TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007073 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7074 WINDOW_LOCATION));
7075
7076 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007077 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007078 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007079 // 'notifyConnectionUnresponsive' should only be called once per connection
7080 mFakePolicy->assertNotifyAnrWasNotCalled();
7081 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007082 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007083 mWindow->consumeMotionEvent(
7084 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007085 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007086 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007087 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007088 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007089}
7090
7091/**
7092 * If a window is processing a motion event, and then a key event comes in, the key event should
7093 * not to to the focused window until the motion is processed.
7094 *
7095 * Warning!!!
7096 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7097 * and the injection timeout that we specify when injecting the key.
7098 * We must have the injection timeout (10ms) be smaller than
7099 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7100 *
7101 * If that value changes, this test should also change.
7102 */
7103TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7104 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7105 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7106
7107 tapOnWindow();
7108 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7109 ASSERT_TRUE(downSequenceNum);
7110 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7111 ASSERT_TRUE(upSequenceNum);
7112 // Don't finish the events yet, and send a key
7113 // Injection will "succeed" because we will eventually give up and send the key to the focused
7114 // window even if motions are still being processed. But because the injection timeout is short,
7115 // we will receive INJECTION_TIMED_OUT as the result.
7116
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007117 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007118 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007119 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7120 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007121 // Key will not be sent to the window, yet, because the window is still processing events
7122 // and the key remains pending, waiting for the touch events to be processed
7123 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7124 ASSERT_FALSE(keySequenceNum);
7125
7126 std::this_thread::sleep_for(500ms);
7127 // if we wait long enough though, dispatcher will give up, and still send the key
7128 // to the focused window, even though we have not yet finished the motion event
7129 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7130 mWindow->finishEvent(*downSequenceNum);
7131 mWindow->finishEvent(*upSequenceNum);
7132}
7133
7134/**
7135 * If a window is processing a motion event, and then a key event comes in, the key event should
7136 * not go to the focused window until the motion is processed.
7137 * If then a new motion comes in, then the pending key event should be going to the currently
7138 * focused window right away.
7139 */
7140TEST_F(InputDispatcherSingleWindowAnr,
7141 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7142 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7143 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7144
7145 tapOnWindow();
7146 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7147 ASSERT_TRUE(downSequenceNum);
7148 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7149 ASSERT_TRUE(upSequenceNum);
7150 // Don't finish the events yet, and send a key
7151 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007153 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7154 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007155 // At this point, key is still pending, and should not be sent to the application yet.
7156 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7157 ASSERT_FALSE(keySequenceNum);
7158
7159 // Now tap down again. It should cause the pending key to go to the focused window right away.
7160 tapOnWindow();
7161 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7162 // the other events yet. We can finish events in any order.
7163 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7164 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7165 mWindow->consumeMotionDown();
7166 mWindow->consumeMotionUp();
7167 mWindow->assertNoEvents();
7168}
7169
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007170/**
7171 * Send an event to the app and have the app not respond right away.
7172 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7173 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7174 * At some point, the window becomes responsive again.
7175 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7176 */
7177TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7178 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7179 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7180 .build());
7181
7182 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7183 ASSERT_TRUE(sequenceNum);
7184 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7185 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7186
7187 mWindow->finishEvent(*sequenceNum);
7188 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7189 ASSERT_TRUE(mDispatcher->waitForIdle());
7190 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7191
7192 // Now that the window is responsive, let's continue the gesture.
7193 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7194 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7195 .build());
7196
7197 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7198 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7199 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7200 .build());
7201
7202 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7203 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7204 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7205 .build());
7206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7207 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7208 .build());
7209 // We already canceled this pointer, so the window shouldn't get any new events.
7210 mWindow->assertNoEvents();
7211
7212 // Start another one.
7213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7214 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7215 .build());
7216 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7217}
7218
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007219class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7220 virtual void SetUp() override {
7221 InputDispatcherTest::SetUp();
7222
Chris Yea209fde2020-07-22 13:54:51 -07007223 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007224 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007225 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7226 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007227 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007228 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007229 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007230
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007231 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7232 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007233 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007234 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007235
7236 // Set focused application.
7237 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007238 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007239
7240 // Expect one focus window exist in display.
7241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007242 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007243 mFocusedWindow->consumeFocusEvent(true);
7244 }
7245
7246 virtual void TearDown() override {
7247 InputDispatcherTest::TearDown();
7248
7249 mUnfocusedWindow.clear();
7250 mFocusedWindow.clear();
7251 }
7252
7253protected:
Chris Yea209fde2020-07-22 13:54:51 -07007254 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007255 sp<FakeWindowHandle> mUnfocusedWindow;
7256 sp<FakeWindowHandle> mFocusedWindow;
7257 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7258 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7259 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7260
7261 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7262
7263 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7264
7265private:
7266 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007268 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7269 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007271 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7272 location));
7273 }
7274};
7275
7276// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7277// should be ANR'd first.
7278TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007280 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7281 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007282 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007283 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007284 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007285 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007286 // We consumed all events, so no ANR
7287 ASSERT_TRUE(mDispatcher->waitForIdle());
7288 mFakePolicy->assertNotifyAnrWasNotCalled();
7289
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007291 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7292 FOCUSED_WINDOW_LOCATION));
7293 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7294 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007295
7296 const std::chrono::duration timeout =
7297 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007298 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007299 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7300 // sequence to make it consistent
7301 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007302 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007303 mFocusedWindow->consumeMotionDown();
7304 // This cancel is generated because the connection was unresponsive
7305 mFocusedWindow->consumeMotionCancel();
7306 mFocusedWindow->assertNoEvents();
7307 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007308 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007309 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7310 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007311 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007312}
7313
7314// If we have 2 windows with identical timeouts that are both unresponsive,
7315// it doesn't matter which order they should have ANR.
7316// But we should receive ANR for both.
7317TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7318 // Set the timeout for unfocused window to match the focused window
7319 mUnfocusedWindow->setDispatchingTimeout(10ms);
7320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7321
7322 tapOnFocusedWindow();
7323 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007324 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7325 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7326 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007327
7328 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007329 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7330 mFocusedWindow->getToken() == anrConnectionToken2);
7331 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7332 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007333
7334 ASSERT_TRUE(mDispatcher->waitForIdle());
7335 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007336
7337 mFocusedWindow->consumeMotionDown();
7338 mFocusedWindow->consumeMotionUp();
7339 mUnfocusedWindow->consumeMotionOutside();
7340
Prabir Pradhanedd96402022-02-15 01:46:16 -08007341 sp<IBinder> responsiveToken1, responsiveToken2;
7342 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7343 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007344
7345 // Both applications should be marked as responsive, in any order
7346 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7347 mFocusedWindow->getToken() == responsiveToken2);
7348 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7349 mUnfocusedWindow->getToken() == responsiveToken2);
7350 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007351}
7352
7353// If a window is already not responding, the second tap on the same window should be ignored.
7354// We should also log an error to account for the dropped event (not tested here).
7355// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7356TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7357 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007358 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007359 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007360 // Receive the events, but don't respond
7361 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7362 ASSERT_TRUE(downEventSequenceNum);
7363 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7364 ASSERT_TRUE(upEventSequenceNum);
7365 const std::chrono::duration timeout =
7366 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007367 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007368
7369 // Tap once again
7370 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007371 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7373 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007374 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007375 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7376 FOCUSED_WINDOW_LOCATION));
7377 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7378 // valid touch target
7379 mUnfocusedWindow->assertNoEvents();
7380
7381 // Consume the first tap
7382 mFocusedWindow->finishEvent(*downEventSequenceNum);
7383 mFocusedWindow->finishEvent(*upEventSequenceNum);
7384 ASSERT_TRUE(mDispatcher->waitForIdle());
7385 // The second tap did not go to the focused window
7386 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007387 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007388 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7389 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007390 mFakePolicy->assertNotifyAnrWasNotCalled();
7391}
7392
7393// If you tap outside of all windows, there will not be ANR
7394TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007395 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007396 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7397 LOCATION_OUTSIDE_ALL_WINDOWS));
7398 ASSERT_TRUE(mDispatcher->waitForIdle());
7399 mFakePolicy->assertNotifyAnrWasNotCalled();
7400}
7401
7402// Since the focused window is paused, tapping on it should not produce any events
7403TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7404 mFocusedWindow->setPaused(true);
7405 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7406
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007407 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007408 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7409 FOCUSED_WINDOW_LOCATION));
7410
7411 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7412 ASSERT_TRUE(mDispatcher->waitForIdle());
7413 // Should not ANR because the window is paused, and touches shouldn't go to it
7414 mFakePolicy->assertNotifyAnrWasNotCalled();
7415
7416 mFocusedWindow->assertNoEvents();
7417 mUnfocusedWindow->assertNoEvents();
7418}
7419
7420/**
7421 * If a window is processing a motion event, and then a key event comes in, the key event should
7422 * not to to the focused window until the motion is processed.
7423 * If a different window becomes focused at this time, the key should go to that window instead.
7424 *
7425 * Warning!!!
7426 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7427 * and the injection timeout that we specify when injecting the key.
7428 * We must have the injection timeout (10ms) be smaller than
7429 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7430 *
7431 * If that value changes, this test should also change.
7432 */
7433TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7434 // Set a long ANR timeout to prevent it from triggering
7435 mFocusedWindow->setDispatchingTimeout(2s);
7436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7437
7438 tapOnUnfocusedWindow();
7439 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7440 ASSERT_TRUE(downSequenceNum);
7441 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7442 ASSERT_TRUE(upSequenceNum);
7443 // Don't finish the events yet, and send a key
7444 // Injection will succeed because we will eventually give up and send the key to the focused
7445 // window even if motions are still being processed.
7446
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007447 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007448 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7449 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007451 // Key will not be sent to the window, yet, because the window is still processing events
7452 // and the key remains pending, waiting for the touch events to be processed
7453 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7454 ASSERT_FALSE(keySequenceNum);
7455
7456 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007457 mFocusedWindow->setFocusable(false);
7458 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007459 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007460 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007461
7462 // Focus events should precede the key events
7463 mUnfocusedWindow->consumeFocusEvent(true);
7464 mFocusedWindow->consumeFocusEvent(false);
7465
7466 // Finish the tap events, which should unblock dispatcher
7467 mUnfocusedWindow->finishEvent(*downSequenceNum);
7468 mUnfocusedWindow->finishEvent(*upSequenceNum);
7469
7470 // Now that all queues are cleared and no backlog in the connections, the key event
7471 // can finally go to the newly focused "mUnfocusedWindow".
7472 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7473 mFocusedWindow->assertNoEvents();
7474 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007475 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007476}
7477
7478// When the touch stream is split across 2 windows, and one of them does not respond,
7479// then ANR should be raised and the touch should be canceled for the unresponsive window.
7480// The other window should not be affected by that.
7481TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7482 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007483 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7484 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7485 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007486 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007487 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007488
7489 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007490 mDispatcher->notifyMotion(
7491 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7492 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007493
7494 const std::chrono::duration timeout =
7495 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007496 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007497
7498 mUnfocusedWindow->consumeMotionDown();
7499 mFocusedWindow->consumeMotionDown();
7500 // Focused window may or may not receive ACTION_MOVE
7501 // But it should definitely receive ACTION_CANCEL due to the ANR
7502 InputEvent* event;
7503 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7504 ASSERT_TRUE(moveOrCancelSequenceNum);
7505 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7506 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007507 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007508 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7509 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7510 mFocusedWindow->consumeMotionCancel();
7511 } else {
7512 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7513 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007514 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007515 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7516 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007517
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007518 mUnfocusedWindow->assertNoEvents();
7519 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007520 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007521}
7522
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007523/**
7524 * If we have no focused window, and a key comes in, we start the ANR timer.
7525 * The focused application should add a focused window before the timer runs out to prevent ANR.
7526 *
7527 * If the user touches another application during this time, the key should be dropped.
7528 * Next, if a new focused window comes in, without toggling the focused application,
7529 * then no ANR should occur.
7530 *
7531 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7532 * but in some cases the policy may not update the focused application.
7533 */
7534TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7535 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7536 std::make_shared<FakeApplicationHandle>();
7537 focusedApplication->setDispatchingTimeout(60ms);
7538 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7539 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7540 mFocusedWindow->setFocusable(false);
7541
7542 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7543 mFocusedWindow->consumeFocusEvent(false);
7544
7545 // Send a key. The ANR timer should start because there is no focused window.
7546 // 'focusedApplication' will get blamed if this timer completes.
7547 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007548 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007549 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7550 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7551 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007553
7554 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7555 // then the injected touches won't cause the focused event to get dropped.
7556 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7557 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7558 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7559 // For this test, it means that the key would get delivered to the window once it becomes
7560 // focused.
7561 std::this_thread::sleep_for(10ms);
7562
7563 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007564 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7565 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7566 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007567
7568 // We do not consume the motion right away, because that would require dispatcher to first
7569 // process (== drop) the key event, and by that time, ANR will be raised.
7570 // Set the focused window first.
7571 mFocusedWindow->setFocusable(true);
7572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7573 setFocusedWindow(mFocusedWindow);
7574 mFocusedWindow->consumeFocusEvent(true);
7575 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7576 // to another application. This could be a bug / behaviour in the policy.
7577
7578 mUnfocusedWindow->consumeMotionDown();
7579
7580 ASSERT_TRUE(mDispatcher->waitForIdle());
7581 // Should not ANR because we actually have a focused window. It was just added too slowly.
7582 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7583}
7584
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007585// These tests ensure we cannot send touch events to a window that's positioned behind a window
7586// that has feature NO_INPUT_CHANNEL.
7587// Layout:
7588// Top (closest to user)
7589// mNoInputWindow (above all windows)
7590// mBottomWindow
7591// Bottom (furthest from user)
7592class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7593 virtual void SetUp() override {
7594 InputDispatcherTest::SetUp();
7595
7596 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007597 mNoInputWindow =
7598 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7599 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007600 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007601 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007602 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7603 // It's perfectly valid for this window to not have an associated input channel
7604
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007605 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7606 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007607 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7608
7609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7610 }
7611
7612protected:
7613 std::shared_ptr<FakeApplicationHandle> mApplication;
7614 sp<FakeWindowHandle> mNoInputWindow;
7615 sp<FakeWindowHandle> mBottomWindow;
7616};
7617
7618TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7619 PointF touchedPoint = {10, 10};
7620
Prabir Pradhan678438e2023-04-13 19:32:51 +00007621 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7622 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7623 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007624
7625 mNoInputWindow->assertNoEvents();
7626 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7627 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7628 // and therefore should prevent mBottomWindow from receiving touches
7629 mBottomWindow->assertNoEvents();
7630}
7631
7632/**
7633 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7634 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7635 */
7636TEST_F(InputDispatcherMultiWindowOcclusionTests,
7637 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007638 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7639 "Window with input channel and NO_INPUT_CHANNEL",
7640 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007641
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007642 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007643 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7645
7646 PointF touchedPoint = {10, 10};
7647
Prabir Pradhan678438e2023-04-13 19:32:51 +00007648 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7649 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7650 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007651
7652 mNoInputWindow->assertNoEvents();
7653 mBottomWindow->assertNoEvents();
7654}
7655
Vishnu Nair958da932020-08-21 17:12:37 -07007656class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7657protected:
7658 std::shared_ptr<FakeApplicationHandle> mApp;
7659 sp<FakeWindowHandle> mWindow;
7660 sp<FakeWindowHandle> mMirror;
7661
7662 virtual void SetUp() override {
7663 InputDispatcherTest::SetUp();
7664 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007665 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7666 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7667 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007668 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7669 mWindow->setFocusable(true);
7670 mMirror->setFocusable(true);
7671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7672 }
7673};
7674
7675TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7676 // Request focus on a mirrored window
7677 setFocusedWindow(mMirror);
7678
7679 // window gets focused
7680 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7682 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007683 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7684}
7685
7686// A focused & mirrored window remains focused only if the window and its mirror are both
7687// focusable.
7688TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7689 setFocusedWindow(mMirror);
7690
7691 // window gets focused
7692 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7694 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007695 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7697 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007698 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7699
7700 mMirror->setFocusable(false);
7701 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7702
7703 // window loses focus since one of the windows associated with the token in not focusable
7704 mWindow->consumeFocusEvent(false);
7705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007706 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7707 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007708 mWindow->assertNoEvents();
7709}
7710
7711// A focused & mirrored window remains focused until the window and its mirror both become
7712// invisible.
7713TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7714 setFocusedWindow(mMirror);
7715
7716 // window gets focused
7717 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007718 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7719 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007720 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007721 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7722 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007723 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7724
7725 mMirror->setVisible(false);
7726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7727
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7729 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007730 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7732 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007733 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7734
7735 mWindow->setVisible(false);
7736 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7737
7738 // window loses focus only after all windows associated with the token become invisible.
7739 mWindow->consumeFocusEvent(false);
7740
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007741 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7742 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007743 mWindow->assertNoEvents();
7744}
7745
7746// A focused & mirrored window remains focused until both windows are removed.
7747TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7748 setFocusedWindow(mMirror);
7749
7750 // window gets focused
7751 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7753 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007754 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007757 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7758
7759 // single window is removed but the window token remains focused
7760 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7761
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007764 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7766 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007767 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7768
7769 // Both windows are removed
7770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7771 mWindow->consumeFocusEvent(false);
7772
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007773 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7774 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007775 mWindow->assertNoEvents();
7776}
7777
7778// Focus request can be pending until one window becomes visible.
7779TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7780 // Request focus on an invisible mirror.
7781 mWindow->setVisible(false);
7782 mMirror->setVisible(false);
7783 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7784 setFocusedWindow(mMirror);
7785
7786 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007788 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7789 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007790
7791 mMirror->setVisible(true);
7792 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7793
7794 // window gets focused
7795 mWindow->consumeFocusEvent(true);
7796 // window gets the pending key event
7797 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7798}
Prabir Pradhan99987712020-11-10 18:43:05 -08007799
7800class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7801protected:
7802 std::shared_ptr<FakeApplicationHandle> mApp;
7803 sp<FakeWindowHandle> mWindow;
7804 sp<FakeWindowHandle> mSecondWindow;
7805
7806 void SetUp() override {
7807 InputDispatcherTest::SetUp();
7808 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007809 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007810 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007811 mSecondWindow =
7812 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007813 mSecondWindow->setFocusable(true);
7814
7815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7816 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7817
7818 setFocusedWindow(mWindow);
7819 mWindow->consumeFocusEvent(true);
7820 }
7821
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007822 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007823 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007824 }
7825
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007826 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7827 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007828 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007829 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7830 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007831 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007832 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007833 }
7834};
7835
7836TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7837 // Ensure that capture cannot be obtained for unfocused windows.
7838 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7839 mFakePolicy->assertSetPointerCaptureNotCalled();
7840 mSecondWindow->assertNoEvents();
7841
7842 // Ensure that capture can be enabled from the focus window.
7843 requestAndVerifyPointerCapture(mWindow, true);
7844
7845 // Ensure that capture cannot be disabled from a window that does not have capture.
7846 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7847 mFakePolicy->assertSetPointerCaptureNotCalled();
7848
7849 // Ensure that capture can be disabled from the window with capture.
7850 requestAndVerifyPointerCapture(mWindow, false);
7851}
7852
7853TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007854 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007855
7856 setFocusedWindow(mSecondWindow);
7857
7858 // Ensure that the capture disabled event was sent first.
7859 mWindow->consumeCaptureEvent(false);
7860 mWindow->consumeFocusEvent(false);
7861 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007862 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007863
7864 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007865 notifyPointerCaptureChanged({});
7866 notifyPointerCaptureChanged(request);
7867 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007868 mWindow->assertNoEvents();
7869 mSecondWindow->assertNoEvents();
7870 mFakePolicy->assertSetPointerCaptureNotCalled();
7871}
7872
7873TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007874 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007875
7876 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007877 notifyPointerCaptureChanged({});
7878 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007879
7880 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007881 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007882 mWindow->consumeCaptureEvent(false);
7883 mWindow->assertNoEvents();
7884}
7885
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007886TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7887 requestAndVerifyPointerCapture(mWindow, true);
7888
7889 // The first window loses focus.
7890 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007891 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007892 mWindow->consumeCaptureEvent(false);
7893
7894 // Request Pointer Capture from the second window before the notification from InputReader
7895 // arrives.
7896 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007897 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007898
7899 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007900 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007901
7902 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007903 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007904
7905 mSecondWindow->consumeFocusEvent(true);
7906 mSecondWindow->consumeCaptureEvent(true);
7907}
7908
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007909TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7910 // App repeatedly enables and disables capture.
7911 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7912 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7913 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7914 mFakePolicy->assertSetPointerCaptureCalled(false);
7915 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7916 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7917
7918 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7919 // first request is now stale, this should do nothing.
7920 notifyPointerCaptureChanged(firstRequest);
7921 mWindow->assertNoEvents();
7922
7923 // InputReader notifies that the second request was enabled.
7924 notifyPointerCaptureChanged(secondRequest);
7925 mWindow->consumeCaptureEvent(true);
7926}
7927
Prabir Pradhan7092e262022-05-03 16:51:09 +00007928TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7929 requestAndVerifyPointerCapture(mWindow, true);
7930
7931 // App toggles pointer capture off and on.
7932 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7933 mFakePolicy->assertSetPointerCaptureCalled(false);
7934
7935 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7936 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7937
7938 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7939 // preceding "disable" request.
7940 notifyPointerCaptureChanged(enableRequest);
7941
7942 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7943 // any notifications.
7944 mWindow->assertNoEvents();
7945}
7946
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007947class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7948protected:
7949 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007950
7951 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7952 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7953
7954 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7955 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7956
7957 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7958 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7959 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7960 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7961 MAXIMUM_OBSCURING_OPACITY);
7962
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007963 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7964 static constexpr gui::Uid APP_B_UID{10002};
7965 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007966
7967 sp<FakeWindowHandle> mTouchWindow;
7968
7969 virtual void SetUp() override {
7970 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007971 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007972 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7973 }
7974
7975 virtual void TearDown() override {
7976 InputDispatcherTest::TearDown();
7977 mTouchWindow.clear();
7978 }
7979
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007980 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007981 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007982 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007983 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007984 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007985 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007986 return window;
7987 }
7988
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007989 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007990 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7991 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007992 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007993 // Generate an arbitrary PID based on the UID
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00007994 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007995 return window;
7996 }
7997
7998 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007999 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8000 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8001 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008002 }
8003};
8004
8005TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008006 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008007 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008009
8010 touch();
8011
8012 mTouchWindow->assertNoEvents();
8013}
8014
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008015TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00008016 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
8017 const sp<FakeWindowHandle>& w =
8018 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
8019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8020
8021 touch();
8022
8023 mTouchWindow->assertNoEvents();
8024}
8025
8026TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008027 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
8028 const sp<FakeWindowHandle>& w =
8029 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8030 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8031
8032 touch();
8033
8034 w->assertNoEvents();
8035}
8036
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008037TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008038 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
8039 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008040
8041 touch();
8042
8043 mTouchWindow->consumeAnyMotionDown();
8044}
8045
8046TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008047 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008048 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008049 w->setFrame(Rect(0, 0, 50, 50));
8050 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008051
8052 touch({PointF{100, 100}});
8053
8054 mTouchWindow->consumeAnyMotionDown();
8055}
8056
8057TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008058 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008059 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008060 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8061
8062 touch();
8063
8064 mTouchWindow->consumeAnyMotionDown();
8065}
8066
8067TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
8068 const sp<FakeWindowHandle>& w =
8069 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8070 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008071
8072 touch();
8073
8074 mTouchWindow->consumeAnyMotionDown();
8075}
8076
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008077TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
8078 const sp<FakeWindowHandle>& w =
8079 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8081
8082 touch();
8083
8084 w->assertNoEvents();
8085}
8086
8087/**
8088 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8089 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8090 * window, the occluding window will still receive ACTION_OUTSIDE event.
8091 */
8092TEST_F(InputDispatcherUntrustedTouchesTest,
8093 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8094 const sp<FakeWindowHandle>& w =
8095 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008096 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008097 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8098
8099 touch();
8100
8101 w->consumeMotionOutside();
8102}
8103
8104TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8105 const sp<FakeWindowHandle>& w =
8106 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008107 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008108 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8109
8110 touch();
8111
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008112 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008113}
8114
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008115TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008116 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008117 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8118 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008119 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8120
8121 touch();
8122
8123 mTouchWindow->consumeAnyMotionDown();
8124}
8125
8126TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8127 const sp<FakeWindowHandle>& w =
8128 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8129 MAXIMUM_OBSCURING_OPACITY);
8130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008131
8132 touch();
8133
8134 mTouchWindow->consumeAnyMotionDown();
8135}
8136
8137TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008138 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008139 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8140 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008141 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8142
8143 touch();
8144
8145 mTouchWindow->assertNoEvents();
8146}
8147
8148TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8149 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8150 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008151 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8152 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008153 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008154 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8155 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8157
8158 touch();
8159
8160 mTouchWindow->assertNoEvents();
8161}
8162
8163TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8164 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8165 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008166 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8167 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008168 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008169 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8170 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008171 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8172
8173 touch();
8174
8175 mTouchWindow->consumeAnyMotionDown();
8176}
8177
8178TEST_F(InputDispatcherUntrustedTouchesTest,
8179 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8180 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008181 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8182 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008183 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008184 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8185 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008186 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8187
8188 touch();
8189
8190 mTouchWindow->consumeAnyMotionDown();
8191}
8192
8193TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8194 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008195 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8196 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008197 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008198 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8199 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008200 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008201
8202 touch();
8203
8204 mTouchWindow->assertNoEvents();
8205}
8206
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008207TEST_F(InputDispatcherUntrustedTouchesTest,
8208 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8209 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008210 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8211 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008212 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008213 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8214 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008215 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8216
8217 touch();
8218
8219 mTouchWindow->assertNoEvents();
8220}
8221
8222TEST_F(InputDispatcherUntrustedTouchesTest,
8223 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8224 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008225 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8226 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008227 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008228 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8229 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008230 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8231
8232 touch();
8233
8234 mTouchWindow->consumeAnyMotionDown();
8235}
8236
8237TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8238 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008239 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8240 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008241 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8242
8243 touch();
8244
8245 mTouchWindow->consumeAnyMotionDown();
8246}
8247
8248TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8249 const sp<FakeWindowHandle>& w =
8250 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8252
8253 touch();
8254
8255 mTouchWindow->consumeAnyMotionDown();
8256}
8257
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008258TEST_F(InputDispatcherUntrustedTouchesTest,
8259 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8260 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8261 const sp<FakeWindowHandle>& w =
8262 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8264
8265 touch();
8266
8267 mTouchWindow->assertNoEvents();
8268}
8269
8270TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8271 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8272 const sp<FakeWindowHandle>& w =
8273 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8275
8276 touch();
8277
8278 mTouchWindow->consumeAnyMotionDown();
8279}
8280
8281TEST_F(InputDispatcherUntrustedTouchesTest,
8282 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8283 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8284 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008285 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8286 OPACITY_ABOVE_THRESHOLD);
8287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8288
8289 touch();
8290
8291 mTouchWindow->consumeAnyMotionDown();
8292}
8293
8294TEST_F(InputDispatcherUntrustedTouchesTest,
8295 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8296 const sp<FakeWindowHandle>& w1 =
8297 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8298 OPACITY_BELOW_THRESHOLD);
8299 const sp<FakeWindowHandle>& w2 =
8300 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8301 OPACITY_BELOW_THRESHOLD);
8302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8303
8304 touch();
8305
8306 mTouchWindow->assertNoEvents();
8307}
8308
8309/**
8310 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8311 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8312 * (which alone would result in allowing touches) does not affect the blocking behavior.
8313 */
8314TEST_F(InputDispatcherUntrustedTouchesTest,
8315 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8316 const sp<FakeWindowHandle>& wB =
8317 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8318 OPACITY_BELOW_THRESHOLD);
8319 const sp<FakeWindowHandle>& wC =
8320 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8321 OPACITY_BELOW_THRESHOLD);
8322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8323
8324 touch();
8325
8326 mTouchWindow->assertNoEvents();
8327}
8328
8329/**
8330 * This test is testing that a window from a different UID but with same application token doesn't
8331 * block the touch. Apps can share the application token for close UI collaboration for example.
8332 */
8333TEST_F(InputDispatcherUntrustedTouchesTest,
8334 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8335 const sp<FakeWindowHandle>& w =
8336 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8337 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008338 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8339
8340 touch();
8341
8342 mTouchWindow->consumeAnyMotionDown();
8343}
8344
arthurhungb89ccb02020-12-30 16:19:01 +08008345class InputDispatcherDragTests : public InputDispatcherTest {
8346protected:
8347 std::shared_ptr<FakeApplicationHandle> mApp;
8348 sp<FakeWindowHandle> mWindow;
8349 sp<FakeWindowHandle> mSecondWindow;
8350 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008351 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008352 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8353 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008354
8355 void SetUp() override {
8356 InputDispatcherTest::SetUp();
8357 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008358 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008359 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008360
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008361 mSecondWindow =
8362 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008363 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008364
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008365 mSpyWindow =
8366 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008367 mSpyWindow->setSpy(true);
8368 mSpyWindow->setTrustedOverlay(true);
8369 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8370
arthurhungb89ccb02020-12-30 16:19:01 +08008371 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008373 }
8374
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008375 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8376 switch (fromSource) {
8377 case AINPUT_SOURCE_TOUCHSCREEN:
8378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8379 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8380 ADISPLAY_ID_DEFAULT, {50, 50}))
8381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8382 break;
8383 case AINPUT_SOURCE_STYLUS:
8384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8385 injectMotionEvent(
8386 mDispatcher,
8387 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8388 AINPUT_SOURCE_STYLUS)
8389 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008390 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008391 .x(50)
8392 .y(50))
8393 .build()));
8394 break;
8395 case AINPUT_SOURCE_MOUSE:
8396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8397 injectMotionEvent(
8398 mDispatcher,
8399 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8400 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8401 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008402 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008403 .x(50)
8404 .y(50))
8405 .build()));
8406 break;
8407 default:
8408 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8409 }
arthurhungb89ccb02020-12-30 16:19:01 +08008410
8411 // Window should receive motion event.
8412 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008413 // Spy window should also receive motion event
8414 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008415 }
8416
8417 // Start performing drag, we will create a drag window and transfer touch to it.
8418 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8419 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008420 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008421 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008422 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008423 }
arthurhungb89ccb02020-12-30 16:19:01 +08008424
8425 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008426 mDragWindow =
8427 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008428 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008429 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008430 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008431
8432 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008433 bool transferred =
8434 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008435 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008436 if (transferred) {
8437 mWindow->consumeMotionCancel();
8438 mDragWindow->consumeMotionDown();
8439 }
8440 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008441 }
8442};
8443
8444TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008445 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008446
8447 // Move on window.
8448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8449 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8450 ADISPLAY_ID_DEFAULT, {50, 50}))
8451 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8452 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8453 mWindow->consumeDragEvent(false, 50, 50);
8454 mSecondWindow->assertNoEvents();
8455
8456 // Move to another window.
8457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8458 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8459 ADISPLAY_ID_DEFAULT, {150, 50}))
8460 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8461 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8462 mWindow->consumeDragEvent(true, 150, 50);
8463 mSecondWindow->consumeDragEvent(false, 50, 50);
8464
8465 // Move back to original window.
8466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8467 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8468 ADISPLAY_ID_DEFAULT, {50, 50}))
8469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8471 mWindow->consumeDragEvent(false, 50, 50);
8472 mSecondWindow->consumeDragEvent(true, -50, 50);
8473
8474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8475 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8477 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8478 mWindow->assertNoEvents();
8479 mSecondWindow->assertNoEvents();
8480}
8481
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008482TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008483 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008484
8485 // No cancel event after drag start
8486 mSpyWindow->assertNoEvents();
8487
8488 const MotionEvent secondFingerDownEvent =
8489 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8490 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008491 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8492 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008493 .build();
8494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8495 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8496 InputEventInjectionSync::WAIT_FOR_RESULT))
8497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8498
8499 // Receives cancel for first pointer after next pointer down
8500 mSpyWindow->consumeMotionCancel();
8501 mSpyWindow->consumeMotionDown();
8502
8503 mSpyWindow->assertNoEvents();
8504}
8505
arthurhungf452d0b2021-01-06 00:19:52 +08008506TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008507 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008508
8509 // Move on window.
8510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8511 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8512 ADISPLAY_ID_DEFAULT, {50, 50}))
8513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8514 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8515 mWindow->consumeDragEvent(false, 50, 50);
8516 mSecondWindow->assertNoEvents();
8517
8518 // Move to another window.
8519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8520 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8521 ADISPLAY_ID_DEFAULT, {150, 50}))
8522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8523 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8524 mWindow->consumeDragEvent(true, 150, 50);
8525 mSecondWindow->consumeDragEvent(false, 50, 50);
8526
8527 // drop to another window.
8528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8529 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8530 {150, 50}))
8531 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8532 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008533 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008534 mWindow->assertNoEvents();
8535 mSecondWindow->assertNoEvents();
8536}
8537
arthurhung6d4bed92021-03-17 11:59:33 +08008538TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008539 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008540
8541 // Move on window and keep button pressed.
8542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8543 injectMotionEvent(mDispatcher,
8544 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8545 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008546 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008547 .build()))
8548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8549 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8550 mWindow->consumeDragEvent(false, 50, 50);
8551 mSecondWindow->assertNoEvents();
8552
8553 // Move to another window and release button, expect to drop item.
8554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8555 injectMotionEvent(mDispatcher,
8556 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8557 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008559 .build()))
8560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8561 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8562 mWindow->assertNoEvents();
8563 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008564 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008565
8566 // nothing to the window.
8567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8568 injectMotionEvent(mDispatcher,
8569 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8570 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008572 .build()))
8573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8574 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8575 mWindow->assertNoEvents();
8576 mSecondWindow->assertNoEvents();
8577}
8578
Arthur Hung54745652022-04-20 07:17:41 +00008579TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008580 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008581
8582 // Set second window invisible.
8583 mSecondWindow->setVisible(false);
8584 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8585
8586 // Move on window.
8587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8588 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8589 ADISPLAY_ID_DEFAULT, {50, 50}))
8590 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8591 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8592 mWindow->consumeDragEvent(false, 50, 50);
8593 mSecondWindow->assertNoEvents();
8594
8595 // Move to another window.
8596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8597 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8598 ADISPLAY_ID_DEFAULT, {150, 50}))
8599 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8600 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8601 mWindow->consumeDragEvent(true, 150, 50);
8602 mSecondWindow->assertNoEvents();
8603
8604 // drop to another window.
8605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8606 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8607 {150, 50}))
8608 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8609 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008610 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008611 mWindow->assertNoEvents();
8612 mSecondWindow->assertNoEvents();
8613}
8614
Arthur Hung54745652022-04-20 07:17:41 +00008615TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008616 // Ensure window could track pointerIds if it didn't support split touch.
8617 mWindow->setPreventSplitting(true);
8618
Arthur Hung54745652022-04-20 07:17:41 +00008619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8620 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8621 {50, 50}))
8622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8623 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8624
8625 const MotionEvent secondFingerDownEvent =
8626 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8627 .displayId(ADISPLAY_ID_DEFAULT)
8628 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008629 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8630 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008631 .build();
8632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8633 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8634 InputEventInjectionSync::WAIT_FOR_RESULT))
8635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008636 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008637
8638 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008639 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008640}
8641
8642TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8643 // First down on second window.
8644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8645 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8646 {150, 50}))
8647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8648
8649 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8650
8651 // Second down on first window.
8652 const MotionEvent secondFingerDownEvent =
8653 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8654 .displayId(ADISPLAY_ID_DEFAULT)
8655 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008656 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8657 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008658 .build();
8659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8660 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8661 InputEventInjectionSync::WAIT_FOR_RESULT))
8662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8663 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8664
8665 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008666 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008667
8668 // Move on window.
8669 const MotionEvent secondFingerMoveEvent =
8670 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008672 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8673 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008674 .build();
8675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8676 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8677 InputEventInjectionSync::WAIT_FOR_RESULT));
8678 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8679 mWindow->consumeDragEvent(false, 50, 50);
8680 mSecondWindow->consumeMotionMove();
8681
8682 // Release the drag pointer should perform drop.
8683 const MotionEvent secondFingerUpEvent =
8684 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8685 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008686 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8687 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008688 .build();
8689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8690 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8691 InputEventInjectionSync::WAIT_FOR_RESULT));
8692 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008693 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008694 mWindow->assertNoEvents();
8695 mSecondWindow->consumeMotionMove();
8696}
8697
Arthur Hung3915c1f2022-05-31 07:17:17 +00008698TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008699 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008700
8701 // Update window of second display.
8702 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008703 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008704 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8705
8706 // Let second display has a touch state.
8707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8708 injectMotionEvent(mDispatcher,
8709 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8710 AINPUT_SOURCE_TOUCHSCREEN)
8711 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008712 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008713 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008714 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008715 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008716 // Update window again.
8717 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8718
8719 // Move on window.
8720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8721 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8722 ADISPLAY_ID_DEFAULT, {50, 50}))
8723 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8724 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8725 mWindow->consumeDragEvent(false, 50, 50);
8726 mSecondWindow->assertNoEvents();
8727
8728 // Move to another window.
8729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8730 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8731 ADISPLAY_ID_DEFAULT, {150, 50}))
8732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8733 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8734 mWindow->consumeDragEvent(true, 150, 50);
8735 mSecondWindow->consumeDragEvent(false, 50, 50);
8736
8737 // drop to another window.
8738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8739 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8740 {150, 50}))
8741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8742 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008743 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008744 mWindow->assertNoEvents();
8745 mSecondWindow->assertNoEvents();
8746}
8747
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008748TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8749 startDrag(true, AINPUT_SOURCE_MOUSE);
8750 // Move on window.
8751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8752 injectMotionEvent(mDispatcher,
8753 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8754 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8755 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008756 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008757 .x(50)
8758 .y(50))
8759 .build()))
8760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8761 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8762 mWindow->consumeDragEvent(false, 50, 50);
8763 mSecondWindow->assertNoEvents();
8764
8765 // Move to another window.
8766 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8767 injectMotionEvent(mDispatcher,
8768 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8769 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8770 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008771 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008772 .x(150)
8773 .y(50))
8774 .build()))
8775 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8776 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8777 mWindow->consumeDragEvent(true, 150, 50);
8778 mSecondWindow->consumeDragEvent(false, 50, 50);
8779
8780 // drop to another window.
8781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8782 injectMotionEvent(mDispatcher,
8783 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8784 .buttonState(0)
8785 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008786 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008787 .x(150)
8788 .y(50))
8789 .build()))
8790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8791 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008792 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008793 mWindow->assertNoEvents();
8794 mSecondWindow->assertNoEvents();
8795}
8796
Linnan Lia4659fc2023-07-14 14:36:22 +08008797/**
8798 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
8799 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
8800 */
8801TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
8802 // Down on second window
8803 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8804 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8805 {150, 50}))
8806 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8807
8808 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
8809 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
8810
8811 // Down on first window
8812 const MotionEvent secondFingerDownEvent =
8813 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8814 .displayId(ADISPLAY_ID_DEFAULT)
8815 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8816 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
8817 .build();
8818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8819 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8820 InputEventInjectionSync::WAIT_FOR_RESULT))
8821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8822 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8823 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
8824 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
8825
8826 // Start drag on first window
8827 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
8828
8829 // Trigger cancel
8830 mDispatcher->cancelCurrentTouch();
8831 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
8832 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
8833 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
8834
8835 ASSERT_TRUE(mDispatcher->waitForIdle());
8836 // The D&D finished with nullptr
8837 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
8838
8839 // Remove drag window
8840 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
8841
8842 // Inject a simple gesture, ensure dispatcher not crashed
8843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8844 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8845 PointF{50, 50}))
8846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8847 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8848
8849 const MotionEvent moveEvent =
8850 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8851 .displayId(ADISPLAY_ID_DEFAULT)
8852 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8853 .build();
8854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8855 injectMotionEvent(mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
8856 InputEventInjectionSync::WAIT_FOR_RESULT))
8857 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8858 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
8859
8860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8861 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8862 {50, 50}))
8863 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8864 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
8865}
8866
Vishnu Nair062a8672021-09-03 16:07:44 -07008867class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8868
8869TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008871 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8872 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008873 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008874 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8875 window->setFocusable(true);
8876 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8877 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008878 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008879
8880 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008881 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008882 window->assertNoEvents();
8883
Prabir Pradhan678438e2023-04-13 19:32:51 +00008884 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8885 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008886 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8887 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008888 window->assertNoEvents();
8889
8890 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008891 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008892 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8893
Prabir Pradhan678438e2023-04-13 19:32:51 +00008894 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008895 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8896
Prabir Pradhan678438e2023-04-13 19:32:51 +00008897 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8898 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008899 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8900 window->assertNoEvents();
8901}
8902
8903TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8904 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8905 std::make_shared<FakeApplicationHandle>();
8906 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008907 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8908 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008909 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008910 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008911 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008913 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8914 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008915 window->setDropInputIfObscured(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008916 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008917 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8918 window->setFocusable(true);
8919 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8920 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008921 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008922
8923 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008924 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008925 window->assertNoEvents();
8926
Prabir Pradhan678438e2023-04-13 19:32:51 +00008927 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8928 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008929 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8930 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008931 window->assertNoEvents();
8932
8933 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008934 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008935 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8936
Prabir Pradhan678438e2023-04-13 19:32:51 +00008937 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008938 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8939
Prabir Pradhan678438e2023-04-13 19:32:51 +00008940 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8941 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008942 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8943 window->assertNoEvents();
8944}
8945
8946TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8947 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8948 std::make_shared<FakeApplicationHandle>();
8949 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008950 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8951 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008952 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008953 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008954 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008956 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8957 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008958 window->setDropInputIfObscured(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00008959 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008960 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8961 window->setFocusable(true);
8962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8963 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008964 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008965
8966 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008967 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008968 window->assertNoEvents();
8969
Prabir Pradhan678438e2023-04-13 19:32:51 +00008970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8971 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008972 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8973 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008974 window->assertNoEvents();
8975
8976 // When the window is no longer obscured because it went on top, it should get input
8977 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8978
Prabir Pradhan678438e2023-04-13 19:32:51 +00008979 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008980 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8981
Prabir Pradhan678438e2023-04-13 19:32:51 +00008982 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8983 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008984 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8985 window->assertNoEvents();
8986}
8987
Antonio Kantekf16f2832021-09-28 04:39:20 +00008988class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8989protected:
8990 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008991 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008992 sp<FakeWindowHandle> mWindow;
8993 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008994 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008995
8996 void SetUp() override {
8997 InputDispatcherTest::SetUp();
8998
8999 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00009000 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009001 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009002 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009003 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009004 mSecondWindow =
9005 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009006 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00009007 mThirdWindow =
9008 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
9009 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
9010 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009011
9012 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00009013 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
9014 {SECOND_DISPLAY_ID, {mThirdWindow}}});
9015 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009016 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009017
Antonio Kantek15beb512022-06-13 22:35:41 +00009018 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009019 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009020 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07009021 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
9022 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009023 mThirdWindow->assertNoEvents();
9024 }
9025
9026 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
9027 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00009028 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00009029 SECOND_DISPLAY_ID)) {
9030 mWindow->assertNoEvents();
9031 mSecondWindow->assertNoEvents();
9032 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07009033 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00009034 }
9035
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009036 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00009037 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07009038 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
9039 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009040 mWindow->consumeTouchModeEvent(inTouchMode);
9041 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00009042 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00009043 }
9044};
9045
Antonio Kantek26defcf2022-02-08 01:12:27 +00009046TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009047 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00009048 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
9049 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009050 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00009051}
9052
Antonio Kantek26defcf2022-02-08 01:12:27 +00009053TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
9054 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009055 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009056 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009057 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009058 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009059 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07009060 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00009061 mWindow->assertNoEvents();
9062 mSecondWindow->assertNoEvents();
9063}
9064
9065TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
9066 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009067 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009068 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009069 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00009070 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00009071 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00009072}
9073
Antonio Kantekf16f2832021-09-28 04:39:20 +00009074TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08009075 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00009076 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
9077 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009078 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00009079 mWindow->assertNoEvents();
9080 mSecondWindow->assertNoEvents();
9081}
9082
Antonio Kantek15beb512022-06-13 22:35:41 +00009083TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
9084 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
9085 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9086 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009087 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00009088 mWindow->assertNoEvents();
9089 mSecondWindow->assertNoEvents();
9090 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
9091}
9092
Antonio Kantek48710e42022-03-24 14:19:30 -07009093TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
9094 // Interact with the window first.
9095 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
9096 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9097 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9098
9099 // Then remove focus.
9100 mWindow->setFocusable(false);
9101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
9102
9103 // Assert that caller can switch touch mode by owning one of the last interacted window.
9104 const WindowInfo& windowInfo = *mWindow->getInfo();
9105 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
9106 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00009107 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07009108}
9109
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009110class InputDispatcherSpyWindowTest : public InputDispatcherTest {
9111public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009112 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009113 std::shared_ptr<FakeApplicationHandle> application =
9114 std::make_shared<FakeApplicationHandle>();
9115 std::string name = "Fake Spy ";
9116 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009117 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
9118 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009119 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009120 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009121 return spy;
9122 }
9123
9124 sp<FakeWindowHandle> createForeground() {
9125 std::shared_ptr<FakeApplicationHandle> application =
9126 std::make_shared<FakeApplicationHandle>();
9127 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009128 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
9129 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009130 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009131 return window;
9132 }
9133
9134private:
9135 int mSpyCount{0};
9136};
9137
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009138using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009139/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009140 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
9141 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009142TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
9143 ScopedSilentDeath _silentDeath;
9144
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009145 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08009146 spy->setTrustedOverlay(false);
9147 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
9148 ".* not a trusted overlay");
9149}
9150
9151/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009152 * Input injection into a display with a spy window but no foreground windows should succeed.
9153 */
9154TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009155 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9157
9158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9159 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9161 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9162}
9163
9164/**
9165 * Verify the order in which different input windows receive events. The touched foreground window
9166 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9167 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9168 * receive events before ones belows it.
9169 *
9170 * Here, we set up a scenario with four windows in the following Z order from the top:
9171 * spy1, spy2, window, spy3.
9172 * We then inject an event and verify that the foreground "window" receives it first, followed by
9173 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9174 * window.
9175 */
9176TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9177 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009178 auto spy1 = createSpy();
9179 auto spy2 = createSpy();
9180 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009181 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9182 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9183 const size_t numChannels = channels.size();
9184
Michael Wright8e9a8562022-02-09 13:44:29 +00009185 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009186 if (!epollFd.ok()) {
9187 FAIL() << "Failed to create epoll fd";
9188 }
9189
9190 for (size_t i = 0; i < numChannels; i++) {
9191 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9192 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9193 FAIL() << "Failed to add fd to epoll";
9194 }
9195 }
9196
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9198 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9199 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9200
9201 std::vector<size_t> eventOrder;
9202 std::vector<struct epoll_event> events(numChannels);
9203 for (;;) {
9204 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9205 (100ms).count());
9206 if (nFds < 0) {
9207 FAIL() << "Failed to call epoll_wait";
9208 }
9209 if (nFds == 0) {
9210 break; // epoll_wait timed out
9211 }
9212 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009213 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009214 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009215 channels[i]->consumeMotionDown();
9216 }
9217 }
9218
9219 // Verify the order in which the events were received.
9220 EXPECT_EQ(3u, eventOrder.size());
9221 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9222 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9223 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9224}
9225
9226/**
9227 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9228 */
9229TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9230 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009231 auto spy = createSpy();
9232 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009233 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9234
9235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9236 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9238 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9239 spy->assertNoEvents();
9240}
9241
9242/**
9243 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9244 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9245 * to the window.
9246 */
9247TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9248 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009249 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009250 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9251 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9252
9253 // Inject an event outside the spy window's touchable region.
9254 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9255 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9257 window->consumeMotionDown();
9258 spy->assertNoEvents();
9259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9260 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9262 window->consumeMotionUp();
9263 spy->assertNoEvents();
9264
9265 // Inject an event inside the spy window's touchable region.
9266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9267 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9268 {5, 10}))
9269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9270 window->consumeMotionDown();
9271 spy->consumeMotionDown();
9272}
9273
9274/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009275 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009276 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009277 */
9278TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9279 auto window = createForeground();
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009280 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009281 auto spy = createSpy();
9282 spy->setWatchOutsideTouch(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009283 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009284 spy->setFrame(Rect{0, 0, 20, 20});
9285 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9286
9287 // Inject an event outside the spy window's frame and touchable region.
9288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009289 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9290 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9292 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009293 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009294}
9295
9296/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009297 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9298 * pointers that are down within its bounds.
9299 */
9300TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9301 auto windowLeft = createForeground();
9302 windowLeft->setFrame({0, 0, 100, 200});
9303 auto windowRight = createForeground();
9304 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009305 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009306 spy->setFrame({0, 0, 200, 200});
9307 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9308
9309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9310 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9311 {50, 50}))
9312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9313 windowLeft->consumeMotionDown();
9314 spy->consumeMotionDown();
9315
9316 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009317 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009318 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009319 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9320 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009321 .build();
9322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9323 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9324 InputEventInjectionSync::WAIT_FOR_RESULT))
9325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9326 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009327 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009328}
9329
9330/**
9331 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9332 * the spy should receive the second pointer with ACTION_DOWN.
9333 */
9334TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9335 auto window = createForeground();
9336 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009337 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009338 spyRight->setFrame({100, 0, 200, 200});
9339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9340
9341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9342 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9343 {50, 50}))
9344 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9345 window->consumeMotionDown();
9346 spyRight->assertNoEvents();
9347
9348 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009349 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009350 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009351 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9352 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009353 .build();
9354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9355 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9356 InputEventInjectionSync::WAIT_FOR_RESULT))
9357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009358 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009359 spyRight->consumeMotionDown();
9360}
9361
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009362/**
9363 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9364 * windows should be allowed to control split touch.
9365 */
9366TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009367 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009368 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009369 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009370 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009371
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009372 auto window = createForeground();
9373 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009374
9375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9376
9377 // First finger down, no window touched.
9378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9379 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9380 {100, 200}))
9381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9382 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9383 window->assertNoEvents();
9384
9385 // Second finger down on window, the window should receive touch down.
9386 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009387 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009388 .displayId(ADISPLAY_ID_DEFAULT)
9389 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009390 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9391 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009392 .build();
9393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9394 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9395 InputEventInjectionSync::WAIT_FOR_RESULT))
9396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9397
9398 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009399 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009400}
9401
9402/**
9403 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9404 * do not receive key events.
9405 */
9406TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009407 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009408 spy->setFocusable(false);
9409
9410 auto window = createForeground();
9411 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9412 setFocusedWindow(window);
9413 window->consumeFocusEvent(true);
9414
9415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9416 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9417 window->consumeKeyDown(ADISPLAY_ID_NONE);
9418
9419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9420 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9421 window->consumeKeyUp(ADISPLAY_ID_NONE);
9422
9423 spy->assertNoEvents();
9424}
9425
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009426using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9427
9428/**
9429 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9430 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9431 */
9432TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9433 auto window = createForeground();
9434 auto spy1 = createSpy();
9435 auto spy2 = createSpy();
9436 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9437
9438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9439 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9440 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9441 window->consumeMotionDown();
9442 spy1->consumeMotionDown();
9443 spy2->consumeMotionDown();
9444
9445 // Pilfer pointers from the second spy window.
9446 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9447 spy2->assertNoEvents();
9448 spy1->consumeMotionCancel();
9449 window->consumeMotionCancel();
9450
9451 // The rest of the gesture should only be sent to the second spy window.
9452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9453 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9454 ADISPLAY_ID_DEFAULT))
9455 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9456 spy2->consumeMotionMove();
9457 spy1->assertNoEvents();
9458 window->assertNoEvents();
9459}
9460
9461/**
9462 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9463 * in the middle of the gesture.
9464 */
9465TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9466 auto window = createForeground();
9467 auto spy = createSpy();
9468 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9469
9470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9471 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9473 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9474 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9475
9476 window->releaseChannel();
9477
9478 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9479
9480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9481 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9483 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9484}
9485
9486/**
9487 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9488 * the spy, but not to any other windows.
9489 */
9490TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9491 auto spy = createSpy();
9492 auto window = createForeground();
9493
9494 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9495
9496 // First finger down on the window and the spy.
9497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9498 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9499 {100, 200}))
9500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9501 spy->consumeMotionDown();
9502 window->consumeMotionDown();
9503
9504 // Spy window pilfers the pointers.
9505 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9506 window->consumeMotionCancel();
9507
9508 // Second finger down on the window and spy, but the window should not receive the pointer down.
9509 const MotionEvent secondFingerDownEvent =
9510 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9511 .displayId(ADISPLAY_ID_DEFAULT)
9512 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009513 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9514 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009515 .build();
9516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9517 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9518 InputEventInjectionSync::WAIT_FOR_RESULT))
9519 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9520
Harry Cutts33476232023-01-30 19:57:29 +00009521 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009522
9523 // Third finger goes down outside all windows, so injection should fail.
9524 const MotionEvent thirdFingerDownEvent =
9525 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9526 .displayId(ADISPLAY_ID_DEFAULT)
9527 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009528 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9529 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9530 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009531 .build();
9532 ASSERT_EQ(InputEventInjectionResult::FAILED,
9533 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9534 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009535 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009536
9537 spy->assertNoEvents();
9538 window->assertNoEvents();
9539}
9540
9541/**
9542 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9543 */
9544TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9545 auto spy = createSpy();
9546 spy->setFrame(Rect(0, 0, 100, 100));
9547 auto window = createForeground();
9548 window->setFrame(Rect(0, 0, 200, 200));
9549
9550 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9551
9552 // First finger down on the window only
9553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9554 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9555 {150, 150}))
9556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9557 window->consumeMotionDown();
9558
9559 // Second finger down on the spy and window
9560 const MotionEvent secondFingerDownEvent =
9561 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9562 .displayId(ADISPLAY_ID_DEFAULT)
9563 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009564 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9565 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009566 .build();
9567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9568 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9569 InputEventInjectionSync::WAIT_FOR_RESULT))
9570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9571 spy->consumeMotionDown();
9572 window->consumeMotionPointerDown(1);
9573
9574 // Third finger down on the spy and window
9575 const MotionEvent thirdFingerDownEvent =
9576 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9577 .displayId(ADISPLAY_ID_DEFAULT)
9578 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009579 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9580 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9581 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009582 .build();
9583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9584 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9585 InputEventInjectionSync::WAIT_FOR_RESULT))
9586 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9587 spy->consumeMotionPointerDown(1);
9588 window->consumeMotionPointerDown(2);
9589
9590 // Spy window pilfers the pointers.
9591 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9592 window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9593 window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9594
9595 spy->assertNoEvents();
9596 window->assertNoEvents();
9597}
9598
9599/**
9600 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9601 * other windows should be canceled. If this results in the cancellation of all pointers for some
9602 * window, then that window should receive ACTION_CANCEL.
9603 */
9604TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9605 auto spy = createSpy();
9606 spy->setFrame(Rect(0, 0, 100, 100));
9607 auto window = createForeground();
9608 window->setFrame(Rect(0, 0, 200, 200));
9609
9610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9611
9612 // First finger down on both spy and window
9613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9614 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9615 {10, 10}))
9616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9617 window->consumeMotionDown();
9618 spy->consumeMotionDown();
9619
9620 // Second finger down on the spy and window
9621 const MotionEvent secondFingerDownEvent =
9622 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9623 .displayId(ADISPLAY_ID_DEFAULT)
9624 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009625 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9626 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009627 .build();
9628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9629 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9630 InputEventInjectionSync::WAIT_FOR_RESULT))
9631 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9632 spy->consumeMotionPointerDown(1);
9633 window->consumeMotionPointerDown(1);
9634
9635 // Spy window pilfers the pointers.
9636 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9637 window->consumeMotionCancel();
9638
9639 spy->assertNoEvents();
9640 window->assertNoEvents();
9641}
9642
9643/**
9644 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9645 * be sent to other windows
9646 */
9647TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9648 auto spy = createSpy();
9649 spy->setFrame(Rect(0, 0, 100, 100));
9650 auto window = createForeground();
9651 window->setFrame(Rect(0, 0, 200, 200));
9652
9653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9654
9655 // First finger down on both window and spy
9656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9657 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9658 {10, 10}))
9659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9660 window->consumeMotionDown();
9661 spy->consumeMotionDown();
9662
9663 // Spy window pilfers the pointers.
9664 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9665 window->consumeMotionCancel();
9666
9667 // Second finger down on the window only
9668 const MotionEvent secondFingerDownEvent =
9669 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9670 .displayId(ADISPLAY_ID_DEFAULT)
9671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009672 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9673 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009674 .build();
9675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9676 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9677 InputEventInjectionSync::WAIT_FOR_RESULT))
9678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9679 window->consumeMotionDown();
9680 window->assertNoEvents();
9681
9682 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9683 spy->consumeMotionMove();
9684 spy->assertNoEvents();
9685}
9686
Prabir Pradhand65552b2021-10-07 11:23:50 -07009687class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9688public:
9689 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9690 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9691 std::make_shared<FakeApplicationHandle>();
9692 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009693 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9694 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009695 overlay->setFocusable(false);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009696 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009697 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009698 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009699 overlay->setTrustedOverlay(true);
9700
9701 std::shared_ptr<FakeApplicationHandle> application =
9702 std::make_shared<FakeApplicationHandle>();
9703 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009704 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9705 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009706 window->setFocusable(true);
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009707 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009708
9709 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9711 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009712 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009713 return {std::move(overlay), std::move(window)};
9714 }
9715
9716 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009717 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009718 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009719 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009720 }
9721
9722 void sendStylusEvent(int32_t action) {
9723 NotifyMotionArgs motionArgs =
9724 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9725 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009726 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009727 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009728 }
9729};
9730
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009731using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9732
9733TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009734 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009735 ScopedSilentDeath _silentDeath;
9736
Prabir Pradhand65552b2021-10-07 11:23:50 -07009737 auto [overlay, window] = setupStylusOverlayScenario();
9738 overlay->setTrustedOverlay(false);
9739 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9740 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9741 ".* not a trusted overlay");
9742}
9743
9744TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9745 auto [overlay, window] = setupStylusOverlayScenario();
9746 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9747
9748 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9749 overlay->consumeMotionDown();
9750 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9751 overlay->consumeMotionUp();
9752
9753 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9754 window->consumeMotionDown();
9755 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9756 window->consumeMotionUp();
9757
9758 overlay->assertNoEvents();
9759 window->assertNoEvents();
9760}
9761
9762TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9763 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009764 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009765 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9766
9767 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9768 overlay->consumeMotionDown();
9769 window->consumeMotionDown();
9770 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9771 overlay->consumeMotionUp();
9772 window->consumeMotionUp();
9773
9774 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9775 window->consumeMotionDown();
9776 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9777 window->consumeMotionUp();
9778
9779 overlay->assertNoEvents();
9780 window->assertNoEvents();
9781}
9782
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009783/**
9784 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9785 * The scenario is as follows:
9786 * - The stylus interceptor overlay is configured as a spy window.
9787 * - The stylus interceptor spy receives the start of a new stylus gesture.
9788 * - It pilfers pointers and then configures itself to no longer be a spy.
9789 * - The stylus interceptor continues to receive the rest of the gesture.
9790 */
9791TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9792 auto [overlay, window] = setupStylusOverlayScenario();
9793 overlay->setSpy(true);
9794 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9795
9796 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9797 overlay->consumeMotionDown();
9798 window->consumeMotionDown();
9799
9800 // The interceptor pilfers the pointers.
9801 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9802 window->consumeMotionCancel();
9803
9804 // The interceptor configures itself so that it is no longer a spy.
9805 overlay->setSpy(false);
9806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9807
9808 // It continues to receive the rest of the stylus gesture.
9809 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9810 overlay->consumeMotionMove();
9811 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9812 overlay->consumeMotionUp();
9813
9814 window->assertNoEvents();
9815}
9816
Prabir Pradhan5735a322022-04-11 17:23:34 +00009817struct User {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009818 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009819 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009820 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9821 std::unique_ptr<InputDispatcher>& mDispatcher;
9822
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009823 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009824 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9825
9826 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9827 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9828 ADISPLAY_ID_DEFAULT, {100, 200},
9829 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9830 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9831 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9832 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9833 }
9834
9835 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009836 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009837 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009838 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009839 mPolicyFlags);
9840 }
9841
9842 sp<FakeWindowHandle> createWindow() const {
9843 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9844 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009845 sp<FakeWindowHandle> window =
9846 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9847 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009848 window->setOwnerInfo(mPid, mUid);
9849 return window;
9850 }
9851};
9852
9853using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9854
9855TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009856 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009857 auto window = owner.createWindow();
9858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9859
9860 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9861 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9862 window->consumeMotionDown();
9863
9864 setFocusedWindow(window);
9865 window->consumeFocusEvent(true);
9866
9867 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9868 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9869 window->consumeKeyDown(ADISPLAY_ID_NONE);
9870}
9871
9872TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009873 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009874 auto window = owner.createWindow();
9875 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9876
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009877 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009878 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9879 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9880
9881 setFocusedWindow(window);
9882 window->consumeFocusEvent(true);
9883
9884 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9885 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9886 window->assertNoEvents();
9887}
9888
9889TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009890 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009891 auto window = owner.createWindow();
9892 auto spy = owner.createWindow();
9893 spy->setSpy(true);
9894 spy->setTrustedOverlay(true);
9895 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9896
9897 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9898 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9899 spy->consumeMotionDown();
9900 window->consumeMotionDown();
9901}
9902
9903TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009904 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009905 auto window = owner.createWindow();
9906
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009907 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009908 auto randosSpy = rando.createWindow();
9909 randosSpy->setSpy(true);
9910 randosSpy->setTrustedOverlay(true);
9911 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9912
9913 // The event is targeted at owner's window, so injection should succeed, but the spy should
9914 // not receive the event.
9915 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9916 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9917 randosSpy->assertNoEvents();
9918 window->consumeMotionDown();
9919}
9920
9921TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009922 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009923 auto window = owner.createWindow();
9924
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009925 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009926 auto randosSpy = rando.createWindow();
9927 randosSpy->setSpy(true);
9928 randosSpy->setTrustedOverlay(true);
9929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9930
9931 // A user that has injection permission can inject into any window.
9932 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9933 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9934 ADISPLAY_ID_DEFAULT));
9935 randosSpy->consumeMotionDown();
9936 window->consumeMotionDown();
9937
9938 setFocusedWindow(randosSpy);
9939 randosSpy->consumeFocusEvent(true);
9940
9941 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9942 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9943 window->assertNoEvents();
9944}
9945
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009946TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009947 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009948 auto window = owner.createWindow();
9949
Prabir Pradhane59c6dc2023-06-13 19:53:03 +00009950 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009951 auto randosWindow = rando.createWindow();
9952 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9953 randosWindow->setWatchOutsideTouch(true);
9954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9955
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009956 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009957 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9958 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9959 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009960 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009961}
9962
Garfield Tane84e6f92019-08-29 17:28:41 -07009963} // namespace android::inputdispatcher