blob: 6a6312ec7889bfea87eafdaea67a488927c18a8f [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080019
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070020#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080021#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080022#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070023#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070024#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000025#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080026#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080027#include <gtest/gtest.h>
Cody Heiner1feacf42023-06-13 15:29:13 -070028#include <input/EventBuilders.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-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 Pradhanaeebeb42023-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 Pradhanaeebeb42023-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 {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000209 struct AnrResult {
210 sp<IBinder> token{};
211 gui::Pid pid{gui::Pid::INVALID};
212 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800213
Michael Wrightd02c5b62014-02-10 15:10:22 -0800214public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000215 FakeInputDispatcherPolicy() = default;
216 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800217
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800218 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700219 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700220 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700221 EXPECT_EQ(event.getDisplayId(), args.displayId);
222
223 const auto& keyEvent = static_cast<const KeyEvent&>(event);
224 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
225 EXPECT_EQ(keyEvent.getAction(), args.action);
226 });
Jackal Guof9696682018-10-05 12:23:23 +0800227 }
228
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700229 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
230 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700231 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700232 EXPECT_EQ(event.getDisplayId(), args.displayId);
233
234 const auto& motionEvent = static_cast<const MotionEvent&>(event);
235 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
236 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000237 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
238 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
239 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
240 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700241 });
Jackal Guof9696682018-10-05 12:23:23 +0800242 }
243
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700244 void assertFilterInputEventWasNotCalled() {
245 std::scoped_lock lock(mLock);
246 ASSERT_EQ(nullptr, mFilteredEvent);
247 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800248
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800249 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700250 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800251 ASSERT_TRUE(mConfigurationChangedTime)
252 << "Timed out waiting for configuration changed call";
253 ASSERT_EQ(*mConfigurationChangedTime, when);
254 mConfigurationChangedTime = std::nullopt;
255 }
256
257 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700258 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800259 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800260 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800261 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
262 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
263 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
264 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
265 mLastNotifySwitch = std::nullopt;
266 }
267
chaviwfd6d3512019-03-25 13:23:49 -0700268 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700269 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800270 ASSERT_EQ(touchedToken, mOnPointerDownToken);
271 mOnPointerDownToken.clear();
272 }
273
274 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700275 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800276 ASSERT_TRUE(mOnPointerDownToken == nullptr)
277 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700278 }
279
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700280 // This function must be called soon after the expected ANR timer starts,
281 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500282 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700283 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500284 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800285 std::unique_lock lock(mLock);
286 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500287 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800288 ASSERT_NO_FATAL_FAILURE(
289 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500290 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700291 }
292
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000293 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800294 const sp<WindowInfoHandle>& window) {
295 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
296 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
297 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500298 }
299
Prabir Pradhanedd96402022-02-15 01:46:16 -0800300 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
301 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000302 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800303 std::unique_lock lock(mLock);
304 android::base::ScopedLockAssertion assumeLocked(mLock);
305 AnrResult result;
306 ASSERT_NO_FATAL_FAILURE(result =
307 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000308 ASSERT_EQ(expectedToken, result.token);
309 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500310 }
311
Prabir Pradhanedd96402022-02-15 01:46:16 -0800312 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000313 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500314 std::unique_lock lock(mLock);
315 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800316 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
317 const auto& [token, _] = result;
318 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000319 }
320
Prabir Pradhanedd96402022-02-15 01:46:16 -0800321 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000322 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800323 std::unique_lock lock(mLock);
324 android::base::ScopedLockAssertion assumeLocked(mLock);
325 AnrResult result;
326 ASSERT_NO_FATAL_FAILURE(
327 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000328 ASSERT_EQ(expectedToken, result.token);
329 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800330 }
331
332 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000333 sp<IBinder> getResponsiveWindowToken() {
334 std::unique_lock lock(mLock);
335 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800336 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
337 const auto& [token, _] = result;
338 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700339 }
340
341 void assertNotifyAnrWasNotCalled() {
342 std::scoped_lock lock(mLock);
343 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800344 ASSERT_TRUE(mAnrWindows.empty());
345 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500346 << "ANR was not called, but please also consume the 'connection is responsive' "
347 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700348 }
349
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000350 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800351 std::unique_lock lock(mLock);
352 base::ScopedLockAssertion assumeLocked(mLock);
353
354 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
355 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000356 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800357 enabled;
358 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000359 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
360 << ") to be called.";
361 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800362 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000363 auto request = *mPointerCaptureRequest;
364 mPointerCaptureRequest.reset();
365 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800366 }
367
368 void assertSetPointerCaptureNotCalled() {
369 std::unique_lock lock(mLock);
370 base::ScopedLockAssertion assumeLocked(mLock);
371
372 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000373 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800374 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000375 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800376 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000377 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800378 }
379
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700380 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
381 const sp<IBinder>& targetToken) {
382 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800383 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800384 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800385 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800386 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800387 }
388
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800389 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
390 std::unique_lock lock(mLock);
391 base::ScopedLockAssertion assumeLocked(mLock);
392 std::optional<sp<IBinder>> receivedToken =
393 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
394 mNotifyInputChannelBroken);
395 ASSERT_TRUE(receivedToken.has_value());
396 ASSERT_EQ(token, *receivedToken);
397 }
398
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800399 /**
400 * Set policy timeout. A value of zero means next key will not be intercepted.
401 */
402 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
403 mInterceptKeyTimeout = timeout;
404 }
405
Josep del Riob3981622023-04-18 15:49:45 +0000406 void assertUserActivityPoked() {
407 std::scoped_lock lock(mLock);
408 ASSERT_TRUE(mPokedUserActivity) << "Expected user activity to have been poked";
409 }
410
411 void assertUserActivityNotPoked() {
412 std::scoped_lock lock(mLock);
413 ASSERT_FALSE(mPokedUserActivity) << "Expected user activity not to have been poked";
414 }
415
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000416 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000417 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
418 }
419
420 void assertNotifyDeviceInteractionWasNotCalled() {
421 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
422 }
423
Michael Wrightd02c5b62014-02-10 15:10:22 -0800424private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700425 std::mutex mLock;
426 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
427 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
428 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
429 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800430
Prabir Pradhan99987712020-11-10 18:43:05 -0800431 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000432
433 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800434
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700435 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700436 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800437 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
438 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700439 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800440 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
441 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700442
arthurhungf452d0b2021-01-06 00:19:52 +0800443 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800444 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Josep del Riob3981622023-04-18 15:49:45 +0000445 bool mPokedUserActivity GUARDED_BY(mLock) = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800446
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800447 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
448
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000449 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000450
Prabir Pradhanedd96402022-02-15 01:46:16 -0800451 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
452 // for a specific container to become non-empty. When the container is non-empty, return the
453 // first entry from the container and erase it.
454 template <class T>
455 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
456 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
457 // If there is an ANR, Dispatcher won't be idle because there are still events
458 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
459 // before checking if ANR was called.
460 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
461 // to provide it some time to act. 100ms seems reasonable.
462 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
463 const std::chrono::time_point start = std::chrono::steady_clock::now();
464 std::optional<T> token =
465 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
466 if (!token.has_value()) {
467 ADD_FAILURE() << "Did not receive the ANR callback";
468 return {};
469 }
470
471 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
472 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
473 // the dispatcher started counting before this function was called
474 if (std::chrono::abs(timeout - waited) > 100ms) {
475 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
476 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
477 << "ms, but waited "
478 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
479 << "ms instead";
480 }
481 return *token;
482 }
483
484 template <class T>
485 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
486 std::queue<T>& storage,
487 std::unique_lock<std::mutex>& lock,
488 std::condition_variable& condition)
489 REQUIRES(mLock) {
490 condition.wait_for(lock, timeout,
491 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
492 if (storage.empty()) {
493 ADD_FAILURE() << "Did not receive the expected callback";
494 return std::nullopt;
495 }
496 T item = storage.front();
497 storage.pop();
498 return std::make_optional(item);
499 }
500
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600501 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700502 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800503 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800504 }
505
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000506 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800507 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700508 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800509 ASSERT_TRUE(pid.has_value());
510 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700511 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500512 }
513
Prabir Pradhanedd96402022-02-15 01:46:16 -0800514 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000515 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500516 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800517 ASSERT_TRUE(pid.has_value());
518 mResponsiveWindows.push({connectionToken, *pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500519 mNotifyAnr.notify_all();
520 }
521
522 void notifyNoFocusedWindowAnr(
523 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
524 std::scoped_lock lock(mLock);
525 mAnrApplications.push(applicationHandle);
526 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800527 }
528
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800529 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
530 std::scoped_lock lock(mLock);
531 mBrokenInputChannels.push(connectionToken);
532 mNotifyInputChannelBroken.notify_all();
533 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800534
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600535 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700536
Chris Yef59a2f42020-10-16 12:55:26 -0700537 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
538 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
539 const std::vector<float>& values) override {}
540
541 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
542 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000543
Chris Yefb552902021-02-03 17:18:37 -0800544 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
545
Prabir Pradhana41d2442023-04-20 21:30:40 +0000546 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700547 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000548 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700549 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000550 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
551 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800552 break;
553 }
554
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000556 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
557 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800558 break;
559 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700560 default: {
561 ADD_FAILURE() << "Should only filter keys or motions";
562 break;
563 }
Jackal Guof9696682018-10-05 12:23:23 +0800564 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 return true;
566 }
567
Prabir Pradhana41d2442023-04-20 21:30:40 +0000568 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
569 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800570 // Clear intercept state when we handled the event.
571 mInterceptKeyTimeout = 0ms;
572 }
573 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800574
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600575 void interceptMotionBeforeQueueing(int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800576
Prabir Pradhana41d2442023-04-20 21:30:40 +0000577 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800578 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
579 // Clear intercept state so we could dispatch the event in next wake.
580 mInterceptKeyTimeout = 0ms;
581 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582 }
583
Prabir Pradhana41d2442023-04-20 21:30:40 +0000584 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent&,
585 uint32_t) override {
586 return {};
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587 }
588
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600589 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
590 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700591 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800592 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
593 * essentially a passthrough for notifySwitch.
594 */
Harry Cutts33476232023-01-30 19:57:29 +0000595 mLastNotifySwitch = NotifySwitchArgs(/*id=*/1, when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596 }
597
Josep del Riob3981622023-04-18 15:49:45 +0000598 void pokeUserActivity(nsecs_t, int32_t, int32_t) override {
599 std::scoped_lock lock(mLock);
600 mPokedUserActivity = true;
601 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800602
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600603 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700604 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700605 mOnPointerDownToken = newToken;
606 }
607
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000608 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800609 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000610 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800611 mPointerCaptureChangedCondition.notify_all();
612 }
613
arthurhungf452d0b2021-01-06 00:19:52 +0800614 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
615 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800616 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800617 mDropTargetWindowToken = token;
618 }
619
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000620 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000621 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000622 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
623 }
624
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700625 void assertFilterInputEventWasCalledInternal(
626 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700627 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800628 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700629 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800630 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800631 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800632};
633
Michael Wrightd02c5b62014-02-10 15:10:22 -0800634// --- InputDispatcherTest ---
635
636class InputDispatcherTest : public testing::Test {
637protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000638 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700639 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800640
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000641 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000642 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
643 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, STALE_EVENT_TIMEOUT);
Harry Cutts101ee9b2023-07-06 18:04:14 +0000644 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000645 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700646 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800647 }
648
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000649 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700650 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000651 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700652 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800653 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700654
655 /**
656 * Used for debugging when writing the test
657 */
658 void dumpDispatcherState() {
659 std::string dump;
660 mDispatcher->dump(dump);
661 std::stringstream ss(dump);
662 std::string to;
663
664 while (std::getline(ss, to, '\n')) {
665 ALOGE("%s", to.c_str());
666 }
667 }
Vishnu Nair958da932020-08-21 17:12:37 -0700668
Chavi Weingarten847e8512023-03-29 00:26:09 +0000669 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700670 FocusRequest request;
671 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000672 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700673 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
674 request.displayId = window->getInfo()->displayId;
675 mDispatcher->setFocusedWindow(request);
676 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800677};
678
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
680 KeyEvent event;
681
682 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800683 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
684 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000685 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600686 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800687 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000688 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000689 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 << "Should reject key events with undefined action.";
691
692 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800693 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
694 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600695 ARBITRARY_TIME, 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 ACTION_MULTIPLE.";
700}
701
702TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
703 MotionEvent event;
704 PointerProperties pointerProperties[MAX_POINTERS + 1];
705 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800706 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707 pointerProperties[i].clear();
708 pointerProperties[i].id = i;
709 pointerCoords[i].clear();
710 }
711
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800712 // Some constants commonly used below
713 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
714 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
715 constexpr int32_t metaState = AMETA_NONE;
716 constexpr MotionClassification classification = MotionClassification::NONE;
717
chaviw9eaa22c2020-07-01 16:21:27 -0700718 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800719 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000721 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700722 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700723 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
724 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000725 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800726 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000727 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000728 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800729 << "Should reject motion events with undefined action.";
730
731 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800732 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800733 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
734 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
735 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
736 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000737 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000739 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000740 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800741 << "Should reject motion events with pointer down index too large.";
742
Garfield Tanfbe732e2020-01-24 11:26:14 -0800743 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700744 AMOTION_EVENT_ACTION_POINTER_DOWN |
745 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700746 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
747 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700748 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800750 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000751 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000752 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800753 << "Should reject motion events with pointer down index too small.";
754
755 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800756 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800757 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
758 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
759 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
760 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000761 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000763 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000764 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800765 << "Should reject motion events with pointer up index too large.";
766
Garfield Tanfbe732e2020-01-24 11:26:14 -0800767 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700768 AMOTION_EVENT_ACTION_POINTER_UP |
769 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700770 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
771 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700772 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000773 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000775 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000776 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800777 << "Should reject motion events with pointer up index too small.";
778
779 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
781 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700782 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700783 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
784 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000785 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800786 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000787 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000788 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800789 << "Should reject motion events with 0 pointers.";
790
Garfield Tanfbe732e2020-01-24 11:26:14 -0800791 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
792 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700793 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700794 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
795 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000796 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000798 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000799 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800800 << "Should reject motion events with more than MAX_POINTERS pointers.";
801
802 // Rejects motion events with invalid pointer ids.
803 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800804 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
805 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700806 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700807 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
808 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000809 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800810 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000811 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000812 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800813 << "Should reject motion events with pointer ids less than 0.";
814
815 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800816 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
817 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700818 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700819 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
820 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000821 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800822 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000823 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000824 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800825 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
826
827 // Rejects motion events with duplicate pointer ids.
828 pointerProperties[0].id = 1;
829 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800830 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
831 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700832 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700833 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
834 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000835 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800836 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000837 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000838 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800839 << "Should reject motion events with duplicate pointer ids.";
840}
841
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800842/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
843
844TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
845 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000846 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800847 ASSERT_TRUE(mDispatcher->waitForIdle());
848
849 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
850}
851
852TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Harry Cutts33476232023-01-30 19:57:29 +0000853 NotifySwitchArgs args(/*id=*/10, /*eventTime=*/20, /*policyFlags=*/0, /*switchValues=*/1,
854 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000855 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800856
857 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
858 args.policyFlags |= POLICY_FLAG_TRUSTED;
859 mFakePolicy->assertNotifySwitchWasCalled(args);
860}
861
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700862namespace {
863
Arthur Hungb92218b2018-08-14 12:00:21 +0800864// --- InputDispatcherTest SetInputWindowTest ---
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700865static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700866// Default input dispatching timeout if there is no focused application or paused window
867// from which to determine an appropriate dispatching timeout.
868static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
869 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
870 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800871
872class FakeApplicationHandle : public InputApplicationHandle {
873public:
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700874 FakeApplicationHandle() {
875 mInfo.name = "Fake Application";
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -0700876 mInfo.token = sp<BBinder>::make();
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500877 mInfo.dispatchingTimeoutMillis =
878 std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700879 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800880 virtual ~FakeApplicationHandle() {}
881
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000882 virtual bool updateInfo() override { return true; }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700883
Siarhei Vishniakou70622952020-07-30 11:17:23 -0500884 void setDispatchingTimeout(std::chrono::milliseconds timeout) {
885 mInfo.dispatchingTimeoutMillis = timeout.count();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700886 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800887};
888
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800889class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800890public:
Garfield Tan15601662020-09-22 15:32:38 -0700891 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
chaviwd1c23182019-12-20 18:44:56 -0800892 : mName(name) {
Garfield Tan15601662020-09-22 15:32:38 -0700893 mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
chaviwd1c23182019-12-20 18:44:56 -0800894 }
895
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800896 InputEvent* consume() {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700897 InputEvent* event;
898 std::optional<uint32_t> consumeSeq = receiveEvent(&event);
899 if (!consumeSeq) {
900 return nullptr;
901 }
902 finishEvent(*consumeSeq);
903 return event;
904 }
905
906 /**
907 * Receive an event without acknowledging it.
908 * Return the sequence number that could later be used to send finished signal.
909 */
910 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800911 uint32_t consumeSeq;
912 InputEvent* event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800913
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800914 std::chrono::time_point start = std::chrono::steady_clock::now();
915 status_t status = WOULD_BLOCK;
916 while (status == WOULD_BLOCK) {
Harry Cutts33476232023-01-30 19:57:29 +0000917 status = mConsumer->consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800918 &event);
919 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
920 if (elapsed > 100ms) {
921 break;
922 }
923 }
924
925 if (status == WOULD_BLOCK) {
926 // Just means there's no event available.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700927 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800928 }
929
930 if (status != OK) {
931 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700932 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800933 }
934 if (event == nullptr) {
935 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700936 return std::nullopt;
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800937 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700938 if (outEvent != nullptr) {
939 *outEvent = event;
940 }
941 return consumeSeq;
942 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800943
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700944 /**
945 * To be used together with "receiveEvent" to complete the consumption of an event.
946 */
947 void finishEvent(uint32_t consumeSeq) {
948 const status_t status = mConsumer->sendFinishedSignal(consumeSeq, true);
949 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950 }
951
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000952 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
953 const status_t status = mConsumer->sendTimeline(inputEventId, timeline);
954 ASSERT_EQ(OK, status);
955 }
956
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700957 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000958 std::optional<int32_t> expectedDisplayId,
959 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960 InputEvent* event = consume();
961
962 ASSERT_NE(nullptr, event) << mName.c_str()
963 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800964 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700965 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
966 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800967
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000968 if (expectedDisplayId.has_value()) {
969 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
970 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800971
Tiger Huang8664f8c2018-10-11 19:14:35 +0800972 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800974 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
975 EXPECT_EQ(expectedAction, keyEvent.getAction());
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000976 if (expectedFlags.has_value()) {
977 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
978 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 break;
980 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800982 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000983 assertMotionAction(expectedAction, motionEvent.getAction());
984
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000985 if (expectedFlags.has_value()) {
986 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
987 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800988 break;
989 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700990 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100991 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
992 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700993 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800994 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000997 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001000 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1001 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001002 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001003 }
1004
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001005 MotionEvent* consumeMotion() {
1006 InputEvent* event = consume();
1007
1008 if (event == nullptr) {
1009 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1010 return nullptr;
1011 }
1012
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001013 if (event->getType() != InputEventType::MOTION) {
1014 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001015 return nullptr;
1016 }
1017 return static_cast<MotionEvent*>(event);
1018 }
1019
1020 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1021 MotionEvent* motionEvent = consumeMotion();
1022 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1023 ASSERT_THAT(*motionEvent, matcher);
1024 }
1025
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001026 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
1027 InputEvent* event = consume();
1028 ASSERT_NE(nullptr, event) << mName.c_str()
1029 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001030 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1031 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032
1033 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1034 << mName.c_str() << ": event displayId should always be NONE.";
1035
1036 FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
1037 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038 }
1039
Prabir Pradhan99987712020-11-10 18:43:05 -08001040 void consumeCaptureEvent(bool hasCapture) {
1041 const InputEvent* event = consume();
1042 ASSERT_NE(nullptr, event) << mName.c_str()
1043 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001044 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1045 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001046
1047 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1048 << mName.c_str() << ": event displayId should always be NONE.";
1049
1050 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1051 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1052 }
1053
arthurhungb89ccb02020-12-30 16:19:01 +08001054 void consumeDragEvent(bool isExiting, float x, float y) {
1055 const InputEvent* event = consume();
1056 ASSERT_NE(nullptr, event) << mName.c_str()
1057 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001058 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001059
1060 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1061 << mName.c_str() << ": event displayId should always be NONE.";
1062
1063 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1064 EXPECT_EQ(isExiting, dragEvent.isExiting());
1065 EXPECT_EQ(x, dragEvent.getX());
1066 EXPECT_EQ(y, dragEvent.getY());
1067 }
1068
Antonio Kantekf16f2832021-09-28 04:39:20 +00001069 void consumeTouchModeEvent(bool inTouchMode) {
1070 const InputEvent* event = consume();
1071 ASSERT_NE(nullptr, event) << mName.c_str()
1072 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1074 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075
1076 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1077 << mName.c_str() << ": event displayId should always be NONE.";
1078 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1079 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1080 }
1081
chaviwd1c23182019-12-20 18:44:56 -08001082 void assertNoEvents() {
1083 InputEvent* event = consume();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001084 if (event == nullptr) {
1085 return;
1086 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001087 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001088 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
1089 ADD_FAILURE() << "Received key event "
1090 << KeyEvent::actionToString(keyEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001091 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001092 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1093 ADD_FAILURE() << "Received motion event "
1094 << MotionEvent::actionToString(motionEvent.getAction());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001095 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001096 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1097 ADD_FAILURE() << "Received focus event, hasFocus = "
1098 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001099 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001100 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1101 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1102 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001103 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001104 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1105 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1106 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107 }
1108 FAIL() << mName.c_str()
1109 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001110 }
1111
1112 sp<IBinder> getToken() { return mConsumer->getChannel()->getConnectionToken(); }
1113
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001114 int getChannelFd() { return mConsumer->getChannel()->getFd().get(); }
1115
chaviwd1c23182019-12-20 18:44:56 -08001116protected:
1117 std::unique_ptr<InputConsumer> mConsumer;
1118 PreallocatedInputEventFactory mEventFactory;
1119
1120 std::string mName;
1121};
1122
chaviw3277faf2021-05-19 16:45:23 -05001123class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001124public:
1125 static const int32_t WIDTH = 600;
1126 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001127
Chris Yea209fde2020-07-22 13:54:51 -07001128 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001129 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001130 int32_t displayId, std::optional<sp<IBinder>> token = std::nullopt)
chaviwd1c23182019-12-20 18:44:56 -08001131 : mName(name) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001132 if (token == std::nullopt) {
Garfield Tan15601662020-09-22 15:32:38 -07001133 base::Result<std::unique_ptr<InputChannel>> channel =
1134 dispatcher->createInputChannel(name);
1135 token = (*channel)->getConnectionToken();
1136 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001137 }
1138
1139 inputApplicationHandle->updateInfo();
1140 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1141
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001142 mInfo.token = *token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001143 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001144 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001145 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001146 mInfo.alpha = 1.0;
chaviwd1c23182019-12-20 18:44:56 -08001147 mInfo.frameLeft = 0;
1148 mInfo.frameTop = 0;
1149 mInfo.frameRight = WIDTH;
1150 mInfo.frameBottom = HEIGHT;
chaviw1ff3d1e2020-07-01 15:53:47 -07001151 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001152 mInfo.globalScaleFactor = 1.0;
1153 mInfo.touchableRegion.clear();
1154 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001155 mInfo.ownerPid = WINDOW_PID;
1156 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001157 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001158 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001159 }
1160
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001161 sp<FakeWindowHandle> clone(int32_t displayId) {
1162 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1163 handle->mInfo = mInfo;
1164 handle->mInfo.displayId = displayId;
1165 handle->mInfo.id = sId++;
1166 handle->mInputReceiver = mInputReceiver;
1167 return handle;
1168 }
1169
1170 /**
1171 * This is different from clone, because clone will make a "mirror" window - a window with the
1172 * same token, but a different ID. The original window and the clone window are allowed to be
1173 * sent to the dispatcher at the same time - they can coexist inside the dispatcher.
1174 * This function will create a different object of WindowInfoHandle, but with the same
1175 * properties as the original object - including the ID.
1176 * You can use either the old or the new object to consume the events.
1177 * IMPORTANT: The duplicated object is supposed to replace the original object, and not appear
1178 * at the same time inside dispatcher.
1179 */
1180 sp<FakeWindowHandle> duplicate() {
1181 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mName);
1182 handle->mInfo = mInfo;
1183 handle->mInputReceiver = mInputReceiver;
Arthur Hungabbb9d82021-09-01 14:52:30 +00001184 return handle;
1185 }
1186
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001187 void setTouchable(bool touchable) {
1188 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1189 }
chaviwd1c23182019-12-20 18:44:56 -08001190
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001191 void setFocusable(bool focusable) {
1192 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1193 }
1194
1195 void setVisible(bool visible) {
1196 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1197 }
Vishnu Nair958da932020-08-21 17:12:37 -07001198
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001199 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001200 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001201 }
1202
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001203 void setPaused(bool paused) {
1204 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1205 }
1206
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001207 void setPreventSplitting(bool preventSplitting) {
1208 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001209 }
1210
1211 void setSlippery(bool slippery) {
1212 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1213 }
1214
1215 void setWatchOutsideTouch(bool watchOutside) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1217 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001218
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001219 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1220
1221 void setInterceptsStylus(bool interceptsStylus) {
1222 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1223 }
1224
1225 void setDropInput(bool dropInput) {
1226 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1227 }
1228
1229 void setDropInputIfObscured(bool dropInputIfObscured) {
1230 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1231 }
1232
1233 void setNoInputChannel(bool noInputChannel) {
1234 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1235 }
1236
Josep del Riob3981622023-04-18 15:49:45 +00001237 void setDisableUserActivity(bool disableUserActivity) {
1238 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1239 }
1240
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001241 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1242
chaviw3277faf2021-05-19 16:45:23 -05001243 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001244
Bernardo Rufino7393d172021-02-26 13:56:11 +00001245 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1246
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001247 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001248 mInfo.frameLeft = frame.left;
1249 mInfo.frameTop = frame.top;
1250 mInfo.frameRight = frame.right;
1251 mInfo.frameBottom = frame.bottom;
1252 mInfo.touchableRegion.clear();
1253 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001254
1255 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1256 ui::Transform translate;
1257 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1258 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001259 }
1260
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001261 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1262
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001263 void setIsWallpaper(bool isWallpaper) {
1264 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1265 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001266
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001267 void setDupTouchToWallpaper(bool hasWallpaper) {
1268 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1269 }
chaviwd1c23182019-12-20 18:44:56 -08001270
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001271 void setTrustedOverlay(bool trustedOverlay) {
1272 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1273 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001274
chaviw9eaa22c2020-07-01 16:21:27 -07001275 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1276 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1277 }
1278
1279 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001280
yunho.shinf4a80b82020-11-16 21:13:57 +09001281 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1282
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001283 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001284 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001285 }
1286
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001287 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001288 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001289 }
1290
Svet Ganov5d3bc372020-01-26 23:11:07 -08001291 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001292 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001293 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1294 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001295 }
1296
1297 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001299 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1300 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001301 }
1302
1303 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001304 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001305 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1306 }
1307
1308 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1309 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001310 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001311 expectedFlags);
1312 }
1313
Svet Ganov5d3bc372020-01-26 23:11:07 -08001314 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001315 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1316 int32_t expectedFlags = 0) {
1317 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1318 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001319 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001320 }
1321
1322 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001323 int32_t expectedFlags = 0) {
1324 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1325 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001326 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001327 }
1328
1329 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001330 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001331 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001332 expectedFlags);
1333 }
1334
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001335 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1336 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001337 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001338 expectedFlags);
1339 }
1340
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001341 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1342 int32_t expectedFlags = 0) {
1343 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001344 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001345 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001346 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1347 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1348 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1349 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1350 }
1351
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001352 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1353 ASSERT_NE(mInputReceiver, nullptr)
1354 << "Cannot consume events from a window with no receiver";
1355 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1356 }
1357
Prabir Pradhan99987712020-11-10 18:43:05 -08001358 void consumeCaptureEvent(bool hasCapture) {
1359 ASSERT_NE(mInputReceiver, nullptr)
1360 << "Cannot consume events from a window with no receiver";
1361 mInputReceiver->consumeCaptureEvent(hasCapture);
1362 }
1363
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001364 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1365 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001366 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001367 ASSERT_THAT(*motionEvent, matcher);
1368 }
1369
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001370 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001371 std::optional<int32_t> expectedDisplayId,
1372 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001373 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1374 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1375 expectedFlags);
1376 }
1377
arthurhungb89ccb02020-12-30 16:19:01 +08001378 void consumeDragEvent(bool isExiting, float x, float y) {
1379 mInputReceiver->consumeDragEvent(isExiting, x, y);
1380 }
1381
Antonio Kantekf16f2832021-09-28 04:39:20 +00001382 void consumeTouchModeEvent(bool inTouchMode) {
1383 ASSERT_NE(mInputReceiver, nullptr)
1384 << "Cannot consume events from a window with no receiver";
1385 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1386 }
1387
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001388 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001389 if (mInputReceiver == nullptr) {
1390 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1391 return std::nullopt;
1392 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001393 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001394 }
1395
1396 void finishEvent(uint32_t sequenceNum) {
1397 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1398 mInputReceiver->finishEvent(sequenceNum);
1399 }
1400
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001401 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1402 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1403 mInputReceiver->sendTimeline(inputEventId, timeline);
1404 }
1405
chaviwaf87b3e2019-10-01 16:59:28 -07001406 InputEvent* consume() {
1407 if (mInputReceiver == nullptr) {
1408 return nullptr;
1409 }
1410 return mInputReceiver->consume();
1411 }
1412
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001413 MotionEvent* consumeMotion() {
1414 InputEvent* event = consume();
1415 if (event == nullptr) {
1416 ADD_FAILURE() << "Consume failed : no event";
1417 return nullptr;
1418 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001419 if (event->getType() != InputEventType::MOTION) {
1420 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001421 return nullptr;
1422 }
1423 return static_cast<MotionEvent*>(event);
1424 }
1425
Arthur Hungb92218b2018-08-14 12:00:21 +08001426 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001427 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001428 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001429 return; // Can't receive events if the window does not have input channel
1430 }
1431 ASSERT_NE(nullptr, mInputReceiver)
1432 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001433 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001434 }
1435
chaviwaf87b3e2019-10-01 16:59:28 -07001436 sp<IBinder> getToken() { return mInfo.token; }
1437
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001438 const std::string& getName() { return mName; }
1439
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001440 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001441 mInfo.ownerPid = ownerPid;
1442 mInfo.ownerUid = ownerUid;
1443 }
1444
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001445 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001446
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001447 void destroyReceiver() { mInputReceiver = nullptr; }
1448
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001449 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1450
chaviwd1c23182019-12-20 18:44:56 -08001451private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001452 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001453 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001454 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001455 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001456 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001457};
1458
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001459std::atomic<int32_t> FakeWindowHandle::sId{1};
1460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001461static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001462 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001463 int32_t displayId = ADISPLAY_ID_NONE,
1464 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001465 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001466 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001467 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001468 KeyEvent event;
1469 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1470
1471 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001472 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001473 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1474 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001475
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001476 if (!allowKeyRepeat) {
1477 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1478 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001479 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001480 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001481}
1482
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001483static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001484 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001485 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001486}
1487
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001488// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1489// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1490// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001491static InputEventInjectionResult injectKeyDownNoRepeat(
1492 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001493 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001494 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001495 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001496}
1497
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001498static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001499 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001500 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001501}
1502
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001503static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001504 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001505 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001506 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001507 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001508 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1509 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -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, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001514 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001515 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001516 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1517 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001518 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001519 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001520 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001521 MotionEventBuilder motionBuilder =
1522 MotionEventBuilder(action, source)
1523 .displayId(displayId)
1524 .eventTime(eventTime)
1525 .rawXCursorPosition(cursorPosition.x)
1526 .rawYCursorPosition(cursorPosition.y)
1527 .pointer(
1528 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1529 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1530 motionBuilder.downTime(eventTime);
1531 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001532
1533 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001534 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1535 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001536}
1537
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001538static InputEventInjectionResult injectMotionDown(
1539 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1540 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001541 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001542}
1543
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001544static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001545 int32_t source, int32_t displayId,
1546 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001547 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001548}
1549
Jackal Guof9696682018-10-05 12:23:23 +08001550static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1551 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1552 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001553 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001554 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1555 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001556
1557 return args;
1558}
1559
Josep del Riob3981622023-04-18 15:49:45 +00001560static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1561 int32_t displayId = ADISPLAY_ID_NONE) {
1562 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1563 // Define a valid key event.
1564 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001565 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001566 currentTime);
1567
1568 return args;
1569}
1570
1571static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1572 int32_t displayId = ADISPLAY_ID_NONE) {
1573 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1574 // Define a valid key event.
1575 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001576 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001577 AMETA_NONE, currentTime);
1578
1579 return args;
1580}
1581
Prabir Pradhan678438e2023-04-13 19:32:51 +00001582[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1583 int32_t displayId,
1584 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001585 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001586 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1587 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1588 }
1589
chaviwd1c23182019-12-20 18:44:56 -08001590 PointerProperties pointerProperties[pointerCount];
1591 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001592
chaviwd1c23182019-12-20 18:44:56 -08001593 for (size_t i = 0; i < pointerCount; i++) {
1594 pointerProperties[i].clear();
1595 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001596 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001597
chaviwd1c23182019-12-20 18:44:56 -08001598 pointerCoords[i].clear();
1599 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1600 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1601 }
Jackal Guof9696682018-10-05 12:23:23 +08001602
1603 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001605 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001606 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1607 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001608 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001609 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001610 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001611 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001612
1613 return args;
1614}
1615
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001616static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1617 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1618}
1619
chaviwd1c23182019-12-20 18:44:56 -08001620static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1621 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1622}
1623
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001624static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1625 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001626 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001627}
1628
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001629} // namespace
1630
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001631/**
1632 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1633 * broken channel.
1634 */
1635TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1637 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001638 sp<FakeWindowHandle>::make(application, mDispatcher,
1639 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001640
1641 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1642
1643 // Window closes its channel, but the window remains.
1644 window->destroyReceiver();
1645 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1646}
1647
Arthur Hungb92218b2018-08-14 12:00:21 +08001648TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001650 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1651 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001652
Arthur Hung72d8dc32020-03-28 00:48:39 +00001653 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1655 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001657
1658 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001659 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001660}
1661
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001662TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001664 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1665 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001666
1667 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1668 // Inject a MotionEvent to an unknown display.
1669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1670 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1672
1673 // Window should receive motion event.
1674 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1675}
1676
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001677/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001678 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001679 * This test serves as a sanity check for the next test, where setInputWindows is
1680 * called twice.
1681 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001682TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001684 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1685 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001686 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001687
1688 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001689 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001690 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1691 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001692 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693
1694 // Window should receive motion event.
1695 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1696}
1697
1698/**
1699 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001700 */
1701TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1704 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001705 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001706
1707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1708 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001709 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001710 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1711 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001713
1714 // Window should receive motion event.
1715 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1716}
1717
Arthur Hungb92218b2018-08-14 12:00:21 +08001718// The foreground window should receive the first touch down event.
1719TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001721 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001722 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001723 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001724 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001725
Arthur Hung72d8dc32020-03-28 00:48:39 +00001726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1728 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001730
1731 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001732 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001733 windowSecond->assertNoEvents();
1734}
1735
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001736/**
1737 * Two windows: A top window, and a wallpaper behind the window.
1738 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1739 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001740 * 1. foregroundWindow <-- dup touch to wallpaper
1741 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001742 */
1743TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1745 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001746 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001747 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001748 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001750 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001751
1752 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1754 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1755 {100, 200}))
1756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1757
1758 // Both foreground window and its wallpaper should receive the touch down
1759 foregroundWindow->consumeMotionDown();
1760 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1761
1762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1763 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1764 ADISPLAY_ID_DEFAULT, {110, 200}))
1765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1766
1767 foregroundWindow->consumeMotionMove();
1768 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1769
1770 // Now the foreground window goes away, but the wallpaper stays
1771 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1772 foregroundWindow->consumeMotionCancel();
1773 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1774 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1775}
1776
1777/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001778 * Two fingers down on the window, and lift off the first finger.
1779 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1780 * contains a single pointer.
1781 */
1782TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1783 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1784 sp<FakeWindowHandle> window =
1785 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1786
1787 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001788 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1790 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1791 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001792 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001793 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1794 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1795 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1796 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001797 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001798 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1799 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1800 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1801 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001802 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1803 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1804 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1805
1806 // Remove the window. The gesture should be canceled
1807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1808 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1809 window->consumeMotionEvent(
1810 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1811}
1812
1813/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001814 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1815 * with the following differences:
1816 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1817 * clean up the connection.
1818 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1819 * Ensure that there's no crash in the dispatcher.
1820 */
1821TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1823 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001824 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001825 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001826 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001827 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001828 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001829
1830 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1832 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1833 {100, 200}))
1834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1835
1836 // Both foreground window and its wallpaper should receive the touch down
1837 foregroundWindow->consumeMotionDown();
1838 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1839
1840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1841 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1842 ADISPLAY_ID_DEFAULT, {110, 200}))
1843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1844
1845 foregroundWindow->consumeMotionMove();
1846 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1847
1848 // Wallpaper closes its channel, but the window remains.
1849 wallpaperWindow->destroyReceiver();
1850 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1851
1852 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1853 // is no longer valid.
1854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1855 foregroundWindow->consumeMotionCancel();
1856}
1857
Arthur Hungc539dbb2022-12-08 07:45:36 +00001858class ShouldSplitTouchFixture : public InputDispatcherTest,
1859 public ::testing::WithParamInterface<bool> {};
1860INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1861 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001862/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001863 * A single window that receives touch (on top), and a wallpaper window underneath it.
1864 * The top window gets a multitouch gesture.
1865 * Ensure that wallpaper gets the same gesture.
1866 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001867TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001869 sp<FakeWindowHandle> foregroundWindow =
1870 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1871 foregroundWindow->setDupTouchToWallpaper(true);
1872 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001873
1874 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001875 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001876 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001877
Arthur Hungc539dbb2022-12-08 07:45:36 +00001878 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879
1880 // Touch down on top window
1881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1882 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1883 {100, 100}))
1884 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1885
1886 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001887 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1889
1890 // Second finger down on the top window
1891 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001892 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 .build();
1897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1898 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1899 InputEventInjectionSync::WAIT_FOR_RESULT))
1900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1901
Harry Cutts33476232023-01-30 19:57:29 +00001902 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1903 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001904 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001905
1906 const MotionEvent secondFingerUpEvent =
1907 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1908 .displayId(ADISPLAY_ID_DEFAULT)
1909 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001910 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1911 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001912 .build();
1913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1914 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1915 InputEventInjectionSync::WAIT_FOR_RESULT))
1916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1917 foregroundWindow->consumeMotionPointerUp(0);
1918 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1919
1920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001921 injectMotionEvent(mDispatcher,
1922 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1923 AINPUT_SOURCE_TOUCHSCREEN)
1924 .displayId(ADISPLAY_ID_DEFAULT)
1925 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001926 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001927 .x(100)
1928 .y(100))
1929 .build(),
1930 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1932 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1933 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001934}
1935
1936/**
1937 * Two windows: a window on the left and window on the right.
1938 * A third window, wallpaper, is behind both windows, and spans both top windows.
1939 * The first touch down goes to the left window. A second pointer touches down on the right window.
1940 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1941 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1942 * ACTION_POINTER_DOWN(1).
1943 */
1944TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1946 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001947 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001948 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001949 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001950
1951 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001952 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001953 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001954 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001955
1956 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001957 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001958 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001959 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960
1961 mDispatcher->setInputWindows(
1962 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1963
1964 // Touch down on left window
1965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1966 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1967 {100, 100}))
1968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1969
1970 // Both foreground window and its wallpaper should receive the touch down
1971 leftWindow->consumeMotionDown();
1972 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1973
1974 // Second finger down on the right window
1975 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001976 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001978 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1979 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001980 .build();
1981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1982 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1983 InputEventInjectionSync::WAIT_FOR_RESULT))
1984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1985
1986 leftWindow->consumeMotionMove();
1987 // Since the touch is split, right window gets ACTION_DOWN
1988 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001989 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001990 expectedWallpaperFlags);
1991
1992 // Now, leftWindow, which received the first finger, disappears.
1993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1994 leftWindow->consumeMotionCancel();
1995 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1996 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1997
1998 // The pointer that's still down on the right window moves, and goes to the right window only.
1999 // As far as the dispatcher's concerned though, both pointers are still present.
2000 const MotionEvent secondFingerMoveEvent =
2001 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2002 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002003 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2004 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002005 .build();
2006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2007 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
2008 InputEventInjectionSync::WAIT_FOR_RESULT));
2009 rightWindow->consumeMotionMove();
2010
2011 leftWindow->assertNoEvents();
2012 rightWindow->assertNoEvents();
2013 wallpaperWindow->assertNoEvents();
2014}
2015
Arthur Hungc539dbb2022-12-08 07:45:36 +00002016/**
2017 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2018 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2019 * The right window should receive ACTION_DOWN.
2020 */
2021TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002023 sp<FakeWindowHandle> leftWindow =
2024 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2025 leftWindow->setFrame(Rect(0, 0, 200, 200));
2026 leftWindow->setDupTouchToWallpaper(true);
2027 leftWindow->setSlippery(true);
2028
2029 sp<FakeWindowHandle> rightWindow =
2030 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2031 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002032
2033 sp<FakeWindowHandle> wallpaperWindow =
2034 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2035 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002036
Arthur Hungc539dbb2022-12-08 07:45:36 +00002037 mDispatcher->setInputWindows(
2038 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002039
Arthur Hungc539dbb2022-12-08 07:45:36 +00002040 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2042 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002043 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002045
2046 // Both foreground window and its wallpaper should receive the touch down
2047 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002048 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2049
Arthur Hungc539dbb2022-12-08 07:45:36 +00002050 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2053 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2055
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 leftWindow->consumeMotionCancel();
2057 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2058 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002059}
2060
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002061/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002062 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2063 * interactive, it might stop sending this flag.
2064 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2065 * to have a consistent input stream.
2066 *
2067 * Test procedure:
2068 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2069 * DOWN (new gesture).
2070 *
2071 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2072 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2073 *
2074 * We technically just need a single window here, but we are using two windows (spy on top and a
2075 * regular window below) to emulate the actual situation where it happens on the device.
2076 */
2077TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2079 sp<FakeWindowHandle> spyWindow =
2080 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2081 spyWindow->setFrame(Rect(0, 0, 200, 200));
2082 spyWindow->setTrustedOverlay(true);
2083 spyWindow->setSpy(true);
2084
2085 sp<FakeWindowHandle> window =
2086 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2087 window->setFrame(Rect(0, 0, 200, 200));
2088
2089 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2090 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002091
2092 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002093 mDispatcher->notifyMotion(
2094 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2095 .deviceId(touchDeviceId)
2096 .policyFlags(DEFAULT_POLICY_FLAGS)
2097 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2098 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002099
Prabir Pradhan678438e2023-04-13 19:32:51 +00002100 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2101 .deviceId(touchDeviceId)
2102 .policyFlags(DEFAULT_POLICY_FLAGS)
2103 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2104 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2105 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002106 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2107 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2108 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2109 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2110
2111 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002112 mDispatcher->notifyMotion(
2113 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2114 .deviceId(touchDeviceId)
2115 .policyFlags(0)
2116 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2117 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2118 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002119 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2120 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2121
2122 // We don't need to reset the device to reproduce the issue, but the reset event typically
2123 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002124 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002125
2126 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002127 mDispatcher->notifyMotion(
2128 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2129 .deviceId(touchDeviceId)
2130 .policyFlags(DEFAULT_POLICY_FLAGS)
2131 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2132 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002133 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2134 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2135
2136 // No more events
2137 spyWindow->assertNoEvents();
2138 window->assertNoEvents();
2139}
2140
2141/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002142 * Two windows: a window on the left and a window on the right.
2143 * Mouse is hovered from the right window into the left window.
2144 * Next, we tap on the left window, where the cursor was last seen.
2145 * The second tap is done onto the right window.
2146 * The mouse and tap are from two different devices.
2147 * We technically don't need to set the downtime / eventtime for these events, but setting these
2148 * explicitly helps during debugging.
2149 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2150 * In the buggy implementation, a tap on the right window would cause a crash.
2151 */
2152TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2153 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2154 sp<FakeWindowHandle> leftWindow =
2155 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2156 leftWindow->setFrame(Rect(0, 0, 200, 200));
2157
2158 sp<FakeWindowHandle> rightWindow =
2159 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2160 rightWindow->setFrame(Rect(200, 0, 400, 200));
2161
2162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2163 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2164 // stale.
2165 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2166 const int32_t mouseDeviceId = 6;
2167 const int32_t touchDeviceId = 4;
2168 // Move the cursor from right
2169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2170 injectMotionEvent(mDispatcher,
2171 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2172 AINPUT_SOURCE_MOUSE)
2173 .deviceId(mouseDeviceId)
2174 .downTime(baseTime + 10)
2175 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002176 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002177 .x(300)
2178 .y(100))
2179 .build()));
2180 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2181
2182 // .. to the left window
2183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2184 injectMotionEvent(mDispatcher,
2185 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2186 AINPUT_SOURCE_MOUSE)
2187 .deviceId(mouseDeviceId)
2188 .downTime(baseTime + 10)
2189 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002190 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002191 .x(110)
2192 .y(100))
2193 .build()));
2194 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2195 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2196 // Now tap the left window
2197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2198 injectMotionEvent(mDispatcher,
2199 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2200 AINPUT_SOURCE_TOUCHSCREEN)
2201 .deviceId(touchDeviceId)
2202 .downTime(baseTime + 40)
2203 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002204 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002205 .x(100)
2206 .y(100))
2207 .build()));
2208 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2209 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2210
2211 // release tap
2212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2213 injectMotionEvent(mDispatcher,
2214 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2215 AINPUT_SOURCE_TOUCHSCREEN)
2216 .deviceId(touchDeviceId)
2217 .downTime(baseTime + 40)
2218 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002219 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002220 .x(100)
2221 .y(100))
2222 .build()));
2223 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2224
2225 // Tap the window on the right
2226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2227 injectMotionEvent(mDispatcher,
2228 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2229 AINPUT_SOURCE_TOUCHSCREEN)
2230 .deviceId(touchDeviceId)
2231 .downTime(baseTime + 60)
2232 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002233 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002234 .x(300)
2235 .y(100))
2236 .build()));
2237 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2238
2239 // release tap
2240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2241 injectMotionEvent(mDispatcher,
2242 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2243 AINPUT_SOURCE_TOUCHSCREEN)
2244 .deviceId(touchDeviceId)
2245 .downTime(baseTime + 60)
2246 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002247 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002248 .x(300)
2249 .y(100))
2250 .build()));
2251 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2252
2253 // No more events
2254 leftWindow->assertNoEvents();
2255 rightWindow->assertNoEvents();
2256}
2257
2258/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002259 * Start hovering in a window. While this hover is still active, make another window appear on top.
2260 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2261 * While the top window is present, the hovering is stopped.
2262 * Later, hovering gets resumed again.
2263 * Ensure that new hover gesture is handled correctly.
2264 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2265 * to the window that's currently being hovered over.
2266 */
2267TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2269 sp<FakeWindowHandle> window =
2270 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2271 window->setFrame(Rect(0, 0, 200, 200));
2272
2273 // Only a single window is present at first
2274 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2275
2276 // Start hovering in the window
2277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2279 .build());
2280 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2281
2282 // Now, an obscuring window appears!
2283 sp<FakeWindowHandle> obscuringWindow =
2284 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2285 ADISPLAY_ID_DEFAULT,
2286 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2287 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2288 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2289 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2290 obscuringWindow->setNoInputChannel(true);
2291 obscuringWindow->setFocusable(false);
2292 obscuringWindow->setAlpha(1.0);
2293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2294
2295 // While this new obscuring window is present, the hovering is stopped
2296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2297 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2298 .build());
2299 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2300
2301 // Now the obscuring window goes away.
2302 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2303
2304 // And a new hover gesture starts.
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2307 .build());
2308 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2309}
2310
2311/**
2312 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2313 * the obscuring window.
2314 */
2315TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2317 sp<FakeWindowHandle> window =
2318 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2319 window->setFrame(Rect(0, 0, 200, 200));
2320
2321 // Only a single window is present at first
2322 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2323
2324 // Start hovering in the window
2325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2327 .build());
2328 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2329
2330 // Now, an obscuring window appears!
2331 sp<FakeWindowHandle> obscuringWindow =
2332 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2333 ADISPLAY_ID_DEFAULT,
2334 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2335 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2336 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2337 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2338 obscuringWindow->setNoInputChannel(true);
2339 obscuringWindow->setFocusable(false);
2340 obscuringWindow->setAlpha(1.0);
2341 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2342
2343 // While this new obscuring window is present, the hovering continues. The event can't go to the
2344 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2346 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2347 .build());
2348 obscuringWindow->assertNoEvents();
2349 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2350
2351 // Now the obscuring window goes away.
2352 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2353
2354 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2355 // so it should generate a HOVER_ENTER
2356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2357 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2358 .build());
2359 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2360
2361 // Now the MOVE should be getting dispatched normally
2362 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2363 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2364 .build());
2365 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2366}
2367
2368/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002369 * Two windows: a window on the left and a window on the right.
2370 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2371 * down. Then, on the left window, also place second touch pointer down.
2372 * This test tries to reproduce a crash.
2373 * In the buggy implementation, second pointer down on the left window would cause a crash.
2374 */
2375TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2377 sp<FakeWindowHandle> leftWindow =
2378 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2379 leftWindow->setFrame(Rect(0, 0, 200, 200));
2380
2381 sp<FakeWindowHandle> rightWindow =
2382 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2383 rightWindow->setFrame(Rect(200, 0, 400, 200));
2384
2385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2386
2387 const int32_t touchDeviceId = 4;
2388 const int32_t mouseDeviceId = 6;
2389 NotifyMotionArgs args;
2390
2391 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2393 .deviceId(mouseDeviceId)
2394 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2395 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002396 leftWindow->consumeMotionEvent(
2397 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2398
2399 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002400 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2401 .deviceId(mouseDeviceId)
2402 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2404 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002405
2406 leftWindow->consumeMotionEvent(
2407 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2408 leftWindow->consumeMotionEvent(
2409 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2410
Prabir Pradhan678438e2023-04-13 19:32:51 +00002411 mDispatcher->notifyMotion(
2412 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2413 .deviceId(mouseDeviceId)
2414 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2415 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2416 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2417 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002418 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2419
2420 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2422 .deviceId(touchDeviceId)
2423 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2424 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002425 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2426
2427 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2428
2429 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002430 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2431 .deviceId(touchDeviceId)
2432 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2433 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2434 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002435 leftWindow->consumeMotionEvent(
2436 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2437 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2438 // current implementation.
2439 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2440 rightWindow->consumeMotionEvent(
2441 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2442
2443 leftWindow->assertNoEvents();
2444 rightWindow->assertNoEvents();
2445}
2446
2447/**
2448 * On a single window, use two different devices: mouse and touch.
2449 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2450 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2451 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2452 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2453 * represent a new gesture.
2454 */
2455TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2457 sp<FakeWindowHandle> window =
2458 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2459 window->setFrame(Rect(0, 0, 400, 400));
2460
2461 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2462
2463 const int32_t touchDeviceId = 4;
2464 const int32_t mouseDeviceId = 6;
2465 NotifyMotionArgs args;
2466
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002467 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2469 .deviceId(touchDeviceId)
2470 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2471 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002472 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002473 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2474 .deviceId(touchDeviceId)
2475 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2476 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2477 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002478 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002479 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2480 .deviceId(touchDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2482 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2483 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002484 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2485 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2486 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2487
2488 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2490 .deviceId(mouseDeviceId)
2491 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2493 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002494
2495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002496 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002497 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2498
Prabir Pradhan678438e2023-04-13 19:32:51 +00002499 mDispatcher->notifyMotion(
2500 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2501 .deviceId(mouseDeviceId)
2502 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2503 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2504 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2505 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002506 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2507
2508 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002509 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2510 .deviceId(touchDeviceId)
2511 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2512 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2513 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002514 // The pointer_down event should be ignored
2515 window->assertNoEvents();
2516}
2517
2518/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002519 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2520 * the injected event.
2521 */
2522TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2523 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2524 sp<FakeWindowHandle> window =
2525 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2526 window->setFrame(Rect(0, 0, 400, 400));
2527
2528 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2529
2530 const int32_t touchDeviceId = 4;
2531 NotifyMotionArgs args;
2532 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2533 // completion.
2534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2535 injectMotionEvent(mDispatcher,
2536 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2537 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002538 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002539 .x(50)
2540 .y(50))
2541 .build()));
2542 window->consumeMotionEvent(
2543 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2544
2545 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2546 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2548 .deviceId(touchDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2550 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002551
2552 window->consumeMotionEvent(
2553 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2554 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2555}
2556
2557/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002558 * This test is similar to the test above, but the sequence of injected events is different.
2559 *
2560 * Two windows: a window on the left and a window on the right.
2561 * Mouse is hovered over the left window.
2562 * Next, we tap on the left window, where the cursor was last seen.
2563 *
2564 * After that, we inject one finger down onto the right window, and then a second finger down onto
2565 * the left window.
2566 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2567 * window (first), and then another on the left window (second).
2568 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2569 * In the buggy implementation, second finger down on the left window would cause a crash.
2570 */
2571TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2572 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2573 sp<FakeWindowHandle> leftWindow =
2574 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2575 leftWindow->setFrame(Rect(0, 0, 200, 200));
2576
2577 sp<FakeWindowHandle> rightWindow =
2578 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2579 rightWindow->setFrame(Rect(200, 0, 400, 200));
2580
2581 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2582
2583 const int32_t mouseDeviceId = 6;
2584 const int32_t touchDeviceId = 4;
2585 // Hover over the left window. Keep the cursor there.
2586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2587 injectMotionEvent(mDispatcher,
2588 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2589 AINPUT_SOURCE_MOUSE)
2590 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002591 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002592 .x(50)
2593 .y(50))
2594 .build()));
2595 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2596
2597 // Tap on left window
2598 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2599 injectMotionEvent(mDispatcher,
2600 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2601 AINPUT_SOURCE_TOUCHSCREEN)
2602 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002603 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002604 .x(100)
2605 .y(100))
2606 .build()));
2607
2608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2609 injectMotionEvent(mDispatcher,
2610 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
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 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2618 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2619 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2620
2621 // First finger down on right window
2622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2623 injectMotionEvent(mDispatcher,
2624 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2625 AINPUT_SOURCE_TOUCHSCREEN)
2626 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002627 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002628 .x(300)
2629 .y(100))
2630 .build()));
2631 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2632
2633 // Second finger down on the left window
2634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2635 injectMotionEvent(mDispatcher,
2636 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2637 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002638 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002639 .x(300)
2640 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002641 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002642 .x(100)
2643 .y(100))
2644 .build()));
2645 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2646 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2647
2648 // No more events
2649 leftWindow->assertNoEvents();
2650 rightWindow->assertNoEvents();
2651}
2652
2653/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002654 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2655 * While the touch is down, new hover events from the stylus device should be ignored. After the
2656 * touch is gone, stylus hovering should start working again.
2657 */
2658TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2660 sp<FakeWindowHandle> window =
2661 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2662 window->setFrame(Rect(0, 0, 200, 200));
2663
2664 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2665
2666 const int32_t stylusDeviceId = 5;
2667 const int32_t touchDeviceId = 4;
2668 // Start hovering with stylus
2669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2670 injectMotionEvent(mDispatcher,
2671 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2672 AINPUT_SOURCE_STYLUS)
2673 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002674 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002675 .x(50)
2676 .y(50))
2677 .build()));
2678 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2679
2680 // Finger down on the window
2681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2682 injectMotionEvent(mDispatcher,
2683 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2684 AINPUT_SOURCE_TOUCHSCREEN)
2685 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002686 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002687 .x(100)
2688 .y(100))
2689 .build()));
2690 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2691 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2692
2693 // Try to continue hovering with stylus. Since we are already down, injection should fail
2694 ASSERT_EQ(InputEventInjectionResult::FAILED,
2695 injectMotionEvent(mDispatcher,
2696 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2697 AINPUT_SOURCE_STYLUS)
2698 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002699 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002700 .x(50)
2701 .y(50))
2702 .build()));
2703 // No event should be sent. This event should be ignored because a pointer from another device
2704 // is already down.
2705
2706 // Lift up the finger
2707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2708 injectMotionEvent(mDispatcher,
2709 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2710 AINPUT_SOURCE_TOUCHSCREEN)
2711 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002712 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002713 .x(100)
2714 .y(100))
2715 .build()));
2716 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2717
2718 // Now that the touch is gone, stylus hovering should start working again
2719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2720 injectMotionEvent(mDispatcher,
2721 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2722 AINPUT_SOURCE_STYLUS)
2723 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002724 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002725 .x(50)
2726 .y(50))
2727 .build()));
2728 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2729 // No more events
2730 window->assertNoEvents();
2731}
2732
2733/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002734 * A spy window above a window with no input channel.
2735 * Start hovering with a stylus device, and then tap with it.
2736 * Ensure spy window receives the entire sequence.
2737 */
2738TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2740 sp<FakeWindowHandle> spyWindow =
2741 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2742 spyWindow->setFrame(Rect(0, 0, 200, 200));
2743 spyWindow->setTrustedOverlay(true);
2744 spyWindow->setSpy(true);
2745 sp<FakeWindowHandle> window =
2746 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2747 window->setNoInputChannel(true);
2748 window->setFrame(Rect(0, 0, 200, 200));
2749
2750 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2751
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002752 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002753 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2754 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2755 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002756 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2757 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2759 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002761 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2762
2763 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2765 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2766 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002767 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2768
2769 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002770 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2772 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002773 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2774
2775 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002776 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2777 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2778 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002779 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2780 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002781 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2782 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2783 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002784 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2785
2786 // No more events
2787 spyWindow->assertNoEvents();
2788 window->assertNoEvents();
2789}
2790
2791/**
2792 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2793 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2794 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2795 * While the mouse is down, new move events from the touch device should be ignored.
2796 */
2797TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2798 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2799 sp<FakeWindowHandle> spyWindow =
2800 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2801 spyWindow->setFrame(Rect(0, 0, 200, 200));
2802 spyWindow->setTrustedOverlay(true);
2803 spyWindow->setSpy(true);
2804 sp<FakeWindowHandle> window =
2805 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2806 window->setFrame(Rect(0, 0, 200, 200));
2807
2808 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2809
2810 const int32_t mouseDeviceId = 7;
2811 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002812
2813 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2815 .deviceId(mouseDeviceId)
2816 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2817 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002818 spyWindow->consumeMotionEvent(
2819 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2820 window->consumeMotionEvent(
2821 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2822
2823 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2825 .deviceId(touchDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2827 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002828 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2829 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2830 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2831 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2832
Prabir Pradhan678438e2023-04-13 19:32:51 +00002833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2834 .deviceId(touchDeviceId)
2835 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2836 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002837 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2838 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2839
2840 // Pilfer the stream
2841 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2842 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2843
Prabir Pradhan678438e2023-04-13 19:32:51 +00002844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2845 .deviceId(touchDeviceId)
2846 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2847 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002848 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2849
2850 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2852 .deviceId(mouseDeviceId)
2853 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2854 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2855 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002856
2857 spyWindow->consumeMotionEvent(
2858 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2859 spyWindow->consumeMotionEvent(
2860 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2861 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2862
Prabir Pradhan678438e2023-04-13 19:32:51 +00002863 mDispatcher->notifyMotion(
2864 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2865 .deviceId(mouseDeviceId)
2866 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2867 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2868 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2869 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002870 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2871 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2872
2873 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2875 .deviceId(mouseDeviceId)
2876 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2877 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2880 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2881
2882 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2884 .deviceId(touchDeviceId)
2885 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2886 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002887
2888 // No more events
2889 spyWindow->assertNoEvents();
2890 window->assertNoEvents();
2891}
2892
2893/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002894 * On the display, have a single window, and also an area where there's no window.
2895 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2896 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2897 */
2898TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2900 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002901 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002902
2903 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002904
2905 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002906 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002907
2908 mDispatcher->waitForIdle();
2909 window->assertNoEvents();
2910
2911 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002912 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002913 mDispatcher->waitForIdle();
2914 window->consumeMotionDown();
2915}
2916
2917/**
2918 * Same test as above, but instead of touching the empty space, the first touch goes to
2919 * non-touchable window.
2920 */
2921TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2923 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002924 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002925 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2926 window1->setTouchable(false);
2927 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002928 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002929 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2930
2931 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2932
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002933 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002934 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002935
2936 mDispatcher->waitForIdle();
2937 window1->assertNoEvents();
2938 window2->assertNoEvents();
2939
2940 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002941 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002942 mDispatcher->waitForIdle();
2943 window2->consumeMotionDown();
2944}
2945
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002946/**
2947 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2948 * to the event time of the first ACTION_DOWN sent to the particular window.
2949 */
2950TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2952 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002953 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002954 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2955 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002956 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002957 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2958
2959 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2960
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002961 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002962 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002963
2964 mDispatcher->waitForIdle();
2965 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002966 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002967 window2->assertNoEvents();
2968 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2969 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2970 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2971
2972 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002973 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002974 mDispatcher->waitForIdle();
2975 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002976 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2978 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2979 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2980 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2981
2982 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002983 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002984 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002985 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002986
2987 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002988 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002989 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002990 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002991
2992 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2993 window1->consumeMotionMove();
2994 window1->assertNoEvents();
2995
2996 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002997 mDispatcher->notifyMotion(
2998 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002999 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003000 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003001
Prabir Pradhan678438e2023-04-13 19:32:51 +00003002 mDispatcher->notifyMotion(
3003 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003004 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003005 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003006}
3007
Garfield Tandf26e862020-07-01 20:18:19 -07003008TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003010 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003011 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003012 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003013 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003014 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003015 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003016
3017 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3018
3019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
3020
3021 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003023 injectMotionEvent(mDispatcher,
3024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3025 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003027 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003028 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003029
3030 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003032 injectMotionEvent(mDispatcher,
3033 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3034 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003035 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003036 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003037 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3038 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003039
3040 // Inject a series of mouse events for a mouse click
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_DOWN, AINPUT_SOURCE_MOUSE)
3044 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
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 Vishniakouf372b812023-02-14 18:06:51 -08003047 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3048 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003049
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003051 injectMotionEvent(mDispatcher,
3052 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3053 AINPUT_SOURCE_MOUSE)
3054 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3055 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003056 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003057 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003058 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
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_RELEASE,
3063 AINPUT_SOURCE_MOUSE)
3064 .buttonState(0)
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_RELEASE));
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_UP, AINPUT_SOURCE_MOUSE)
3073 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003074 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003075 .build()));
3076 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3077
3078 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003080 injectMotionEvent(mDispatcher,
3081 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3082 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003083 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003084 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003085 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003086
3087 // No more events
3088 windowLeft->assertNoEvents();
3089 windowRight->assertNoEvents();
3090}
3091
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003092/**
3093 * Put two fingers down (and don't release them) and click the mouse button.
3094 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3095 * currently active gesture should be canceled, and the new one should proceed.
3096 */
3097TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3099 sp<FakeWindowHandle> window =
3100 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3101 window->setFrame(Rect(0, 0, 600, 800));
3102
3103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3104
3105 const int32_t touchDeviceId = 4;
3106 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003107
3108 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003109 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3110 .deviceId(touchDeviceId)
3111 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3112 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003113
Prabir Pradhan678438e2023-04-13 19:32:51 +00003114 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3115 .deviceId(touchDeviceId)
3116 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3117 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3118 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003119 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3120 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3121
3122 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3124 .deviceId(mouseDeviceId)
3125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3127 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003128 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3129 WithPointerCount(2u)));
3130 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3131
Prabir Pradhan678438e2023-04-13 19:32:51 +00003132 mDispatcher->notifyMotion(
3133 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3134 .deviceId(mouseDeviceId)
3135 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3136 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3137 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3138 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003139 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3140
3141 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3142 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003143 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3144 .deviceId(touchDeviceId)
3145 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3146 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3147 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003148 window->assertNoEvents();
3149}
3150
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003151TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3152 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3153
3154 sp<FakeWindowHandle> spyWindow =
3155 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3156 spyWindow->setFrame(Rect(0, 0, 600, 800));
3157 spyWindow->setTrustedOverlay(true);
3158 spyWindow->setSpy(true);
3159 sp<FakeWindowHandle> window =
3160 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3161 window->setFrame(Rect(0, 0, 600, 800));
3162
3163 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3164 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3165
3166 // Send mouse cursor to the window
3167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3168 injectMotionEvent(mDispatcher,
3169 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3170 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003171 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003172 .x(100)
3173 .y(100))
3174 .build()));
3175
3176 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3177 WithSource(AINPUT_SOURCE_MOUSE)));
3178 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3179 WithSource(AINPUT_SOURCE_MOUSE)));
3180
3181 window->assertNoEvents();
3182 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003183}
3184
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003185TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3186 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3187
3188 sp<FakeWindowHandle> spyWindow =
3189 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3190 spyWindow->setFrame(Rect(0, 0, 600, 800));
3191 spyWindow->setTrustedOverlay(true);
3192 spyWindow->setSpy(true);
3193 sp<FakeWindowHandle> window =
3194 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3195 window->setFrame(Rect(0, 0, 600, 800));
3196
3197 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3198 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3199
3200 // Send mouse cursor to the window
3201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3202 injectMotionEvent(mDispatcher,
3203 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3204 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003205 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003206 .x(100)
3207 .y(100))
3208 .build()));
3209
3210 // Move mouse cursor
3211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3212 injectMotionEvent(mDispatcher,
3213 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
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(110)
3217 .y(110))
3218 .build()));
3219
3220 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3221 WithSource(AINPUT_SOURCE_MOUSE)));
3222 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3223 WithSource(AINPUT_SOURCE_MOUSE)));
3224 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3225 WithSource(AINPUT_SOURCE_MOUSE)));
3226 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3227 WithSource(AINPUT_SOURCE_MOUSE)));
3228 // Touch down on the window
3229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3230 injectMotionEvent(mDispatcher,
3231 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3232 AINPUT_SOURCE_TOUCHSCREEN)
3233 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003234 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003235 .x(200)
3236 .y(200))
3237 .build()));
3238 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3239 WithSource(AINPUT_SOURCE_MOUSE)));
3240 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3241 WithSource(AINPUT_SOURCE_MOUSE)));
3242 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3243 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3244 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3245 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3246
3247 // pilfer the motion, retaining the gesture on the spy window.
3248 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3249 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3250 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3251
3252 // Touch UP on the window
3253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3254 injectMotionEvent(mDispatcher,
3255 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3256 AINPUT_SOURCE_TOUCHSCREEN)
3257 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003258 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003259 .x(200)
3260 .y(200))
3261 .build()));
3262 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3263 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3264
3265 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3266 // to send a new gesture. It should again go to both windows (spy and the window below), just
3267 // like the first gesture did, before pilfering. The window configuration has not changed.
3268
3269 // One more tap - DOWN
3270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3271 injectMotionEvent(mDispatcher,
3272 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3273 AINPUT_SOURCE_TOUCHSCREEN)
3274 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003275 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003276 .x(250)
3277 .y(250))
3278 .build()));
3279 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3280 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3281 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3282 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3283
3284 // Touch UP on the window
3285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3286 injectMotionEvent(mDispatcher,
3287 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3288 AINPUT_SOURCE_TOUCHSCREEN)
3289 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003290 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003291 .x(250)
3292 .y(250))
3293 .build()));
3294 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3295 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3296 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3297 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3298
3299 window->assertNoEvents();
3300 spyWindow->assertNoEvents();
3301}
3302
Garfield Tandf26e862020-07-01 20:18:19 -07003303// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3304// directly in this test.
3305TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003307 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003308 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003309 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003310
3311 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3312
3313 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3314
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003316 injectMotionEvent(mDispatcher,
3317 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3318 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003319 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003320 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003321 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003322 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003324 injectMotionEvent(mDispatcher,
3325 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3326 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003327 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003328 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003329 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3330 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003331
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003333 injectMotionEvent(mDispatcher,
3334 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3335 AINPUT_SOURCE_MOUSE)
3336 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3337 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003338 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003339 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003340 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
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_RELEASE,
3345 AINPUT_SOURCE_MOUSE)
3346 .buttonState(0)
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_RELEASE));
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_UP, AINPUT_SOURCE_MOUSE)
3355 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003356 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003357 .build()));
3358 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3359
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003360 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3361 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3362 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003363 injectMotionEvent(mDispatcher,
3364 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3365 AINPUT_SOURCE_MOUSE)
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()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003368 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003369}
3370
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003371/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003372 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3373 * is generated.
3374 */
3375TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3377 sp<FakeWindowHandle> window =
3378 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3379 window->setFrame(Rect(0, 0, 1200, 800));
3380
3381 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3382
3383 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3384
3385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3386 injectMotionEvent(mDispatcher,
3387 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3388 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003389 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003390 .x(300)
3391 .y(400))
3392 .build()));
3393 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3394
3395 // Remove the window, but keep the channel.
3396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3397 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3398}
3399
3400/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003401 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3402 */
3403TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3405 sp<FakeWindowHandle> window =
3406 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3407 window->setFrame(Rect(0, 0, 100, 100));
3408
3409 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3410
3411 const int32_t mouseDeviceId = 7;
3412 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003413
3414 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3416 .deviceId(mouseDeviceId)
3417 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3418 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003419 window->consumeMotionEvent(
3420 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3421
3422 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3424 .deviceId(touchDeviceId)
3425 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3426 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003427
3428 window->consumeMotionEvent(
3429 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3431}
3432
3433/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003434 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003435 * The tap causes a HOVER_EXIT event to be generated because the current event
3436 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003437 */
3438TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3440 sp<FakeWindowHandle> window =
3441 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3442 window->setFrame(Rect(0, 0, 100, 100));
3443
3444 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3445
3446 // Inject a hover_move from mouse.
3447 NotifyMotionArgs motionArgs =
3448 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3449 ADISPLAY_ID_DEFAULT, {{50, 50}});
3450 motionArgs.xCursorPosition = 50;
3451 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003452 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003453 ASSERT_NO_FATAL_FAILURE(
3454 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3455 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003456
3457 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003458 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3459 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3460 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003461 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003462 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3463 WithSource(AINPUT_SOURCE_MOUSE))));
3464
3465 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003466 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3467 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3468
Prabir Pradhan678438e2023-04-13 19:32:51 +00003469 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3470 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003471 ASSERT_NO_FATAL_FAILURE(
3472 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3473 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3474}
3475
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003476TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3478 sp<FakeWindowHandle> windowDefaultDisplay =
3479 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3480 ADISPLAY_ID_DEFAULT);
3481 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3482 sp<FakeWindowHandle> windowSecondDisplay =
3483 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3484 SECOND_DISPLAY_ID);
3485 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3486
3487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3488 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3489
3490 // Set cursor position in window in default display and check that hover enter and move
3491 // events are generated.
3492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3493 injectMotionEvent(mDispatcher,
3494 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3495 AINPUT_SOURCE_MOUSE)
3496 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003497 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003498 .x(300)
3499 .y(600))
3500 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003501 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003502
3503 // Remove all windows in secondary display and check that no event happens on window in
3504 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003505 mDispatcher->setInputWindows(
3506 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003507 windowDefaultDisplay->assertNoEvents();
3508
3509 // Move cursor position in window in default display and check that only hover move
3510 // event is generated and not hover enter event.
3511 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3512 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3514 injectMotionEvent(mDispatcher,
3515 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3516 AINPUT_SOURCE_MOUSE)
3517 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003518 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003519 .x(400)
3520 .y(700))
3521 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003522 windowDefaultDisplay->consumeMotionEvent(
3523 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3524 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003525 windowDefaultDisplay->assertNoEvents();
3526}
3527
Garfield Tan00f511d2019-06-12 16:55:40 -07003528TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003530
3531 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003532 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003533 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003534 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003535 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003536 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003537
3538 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3539
Arthur Hung72d8dc32020-03-28 00:48:39 +00003540 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003541
3542 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3543 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003545 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003546 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003547 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003548 windowRight->assertNoEvents();
3549}
3550
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003551TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003553 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3554 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003555 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003556
Arthur Hung72d8dc32020-03-28 00:48:39 +00003557 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003558 setFocusedWindow(window);
3559
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003560 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003561
Prabir Pradhan678438e2023-04-13 19:32:51 +00003562 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003563
3564 // Window should receive key down event.
3565 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3566
3567 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3568 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003569 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003570 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003571 AKEY_EVENT_FLAG_CANCELED);
3572}
3573
3574TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003576 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3577 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003578
Arthur Hung72d8dc32020-03-28 00:48:39 +00003579 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003580
Prabir Pradhan678438e2023-04-13 19:32:51 +00003581 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3582 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003583
3584 // Window should receive motion down event.
3585 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3586
3587 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3588 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003589 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003590 window->consumeMotionEvent(
3591 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003592}
3593
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003594TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3596 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3597 "Fake Window", ADISPLAY_ID_DEFAULT);
3598
3599 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3600
3601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3602 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3603 .build());
3604
3605 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3606
3607 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3608 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3609 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3610
3611 // After the device has been reset, a new hovering stream can be sent to the window
3612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3613 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3614 .build());
3615 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3616}
3617
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003618TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003620 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3621 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003622 window->setFocusable(true);
3623
3624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3625 setFocusedWindow(window);
3626
3627 window->consumeFocusEvent(true);
3628
Prabir Pradhan678438e2023-04-13 19:32:51 +00003629 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003630 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3631 const nsecs_t injectTime = keyArgs.eventTime;
3632 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003633 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003634 // The dispatching time should be always greater than or equal to intercept key timeout.
3635 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3636 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3637 std::chrono::nanoseconds(interceptKeyTimeout).count());
3638}
3639
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003640/**
3641 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3642 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003643TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003645 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3646 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003647 window->setFocusable(true);
3648
3649 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3650 setFocusedWindow(window);
3651
3652 window->consumeFocusEvent(true);
3653
Prabir Pradhan678438e2023-04-13 19:32:51 +00003654 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003655 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003656
3657 // Set a value that's significantly larger than the default consumption timeout. If the
3658 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3659 mFakePolicy->setInterceptKeyTimeout(600ms);
3660 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3661 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003662 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3663}
3664
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003665/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003666 * Two windows. First is a regular window. Second does not overlap with the first, and has
3667 * WATCH_OUTSIDE_TOUCH.
3668 * Both windows are owned by the same UID.
3669 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3670 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3671 */
3672TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3675 "First Window", ADISPLAY_ID_DEFAULT);
3676 window->setFrame(Rect{0, 0, 100, 100});
3677
3678 sp<FakeWindowHandle> outsideWindow =
3679 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3680 ADISPLAY_ID_DEFAULT);
3681 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3682 outsideWindow->setWatchOutsideTouch(true);
3683 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3684 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3685
3686 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3688 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3689 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003690 window->consumeMotionDown();
3691 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3692 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3693 outsideWindow->consumeMotionEvent(
3694 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3695}
3696
3697/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003698 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3699 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3700 * ACTION_OUTSIDE event is sent per gesture.
3701 */
3702TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3703 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3706 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003707 window->setWatchOutsideTouch(true);
3708 window->setFrame(Rect{0, 0, 100, 100});
3709 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003710 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3711 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003712 secondWindow->setFrame(Rect{100, 100, 200, 200});
3713 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003714 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3715 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003716 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3717 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3718
3719 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003720 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3721 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3722 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003723 window->assertNoEvents();
3724 secondWindow->assertNoEvents();
3725
3726 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3727 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003728 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3729 ADISPLAY_ID_DEFAULT,
3730 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003731 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3732 window->consumeMotionEvent(
3733 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003734 secondWindow->consumeMotionDown();
3735 thirdWindow->assertNoEvents();
3736
3737 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3738 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(
3740 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3741 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003742 window->assertNoEvents();
3743 secondWindow->consumeMotionMove();
3744 thirdWindow->consumeMotionDown();
3745}
3746
Prabir Pradhan814fe082022-07-22 20:22:18 +00003747TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3750 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003751 window->setFocusable(true);
3752
Patrick Williamsd828f302023-04-28 17:52:08 -05003753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003754 setFocusedWindow(window);
3755
3756 window->consumeFocusEvent(true);
3757
Prabir Pradhan678438e2023-04-13 19:32:51 +00003758 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3759 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3760 mDispatcher->notifyKey(keyDown);
3761 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003762
3763 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3764 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3765
3766 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003767 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003768
3769 window->consumeFocusEvent(false);
3770
Prabir Pradhan678438e2023-04-13 19:32:51 +00003771 mDispatcher->notifyKey(keyDown);
3772 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003773 window->assertNoEvents();
3774}
3775
Arthur Hung96483742022-11-15 03:30:48 +00003776TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3779 "Fake Window", ADISPLAY_ID_DEFAULT);
3780 // Ensure window is non-split and have some transform.
3781 window->setPreventSplitting(true);
3782 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003783 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003784
3785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3786 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3787 {50, 50}))
3788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3789 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3790
3791 const MotionEvent secondFingerDownEvent =
3792 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3793 .displayId(ADISPLAY_ID_DEFAULT)
3794 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003795 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3796 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003797 .build();
3798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3799 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3800 InputEventInjectionSync::WAIT_FOR_RESULT))
3801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3802
3803 const MotionEvent* event = window->consumeMotion();
3804 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3805 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3806 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3807 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3808 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3809}
3810
Harry Cuttsb166c002023-05-09 13:06:05 +00003811TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3813 sp<FakeWindowHandle> window =
3814 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3815 window->setFrame(Rect(0, 0, 400, 400));
3816 sp<FakeWindowHandle> trustedOverlay =
3817 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3818 ADISPLAY_ID_DEFAULT);
3819 trustedOverlay->setSpy(true);
3820 trustedOverlay->setTrustedOverlay(true);
3821
3822 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3823
3824 // Start a three-finger touchpad swipe
3825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3826 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3827 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3828 .build());
3829 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3830 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3831 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3832 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3833 .build());
3834 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3835 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3836 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3837 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3838 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3839 .build());
3840
3841 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3842 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3843 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3844
3845 // Move the swipe a bit
3846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3847 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3848 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3849 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3850 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3851 .build());
3852
3853 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3854
3855 // End the swipe
3856 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3857 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3858 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3859 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3860 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3861 .build());
3862 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3863 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3864 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3865 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3866 .build());
3867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3868 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3869 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3870 .build());
3871
3872 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3873 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3874 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3875
3876 window->assertNoEvents();
3877}
3878
3879TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3881 sp<FakeWindowHandle> window =
3882 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3883 window->setFrame(Rect(0, 0, 400, 400));
3884 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3885
3886 // Start a three-finger touchpad swipe
3887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3888 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3889 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3890 .build());
3891 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3892 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3893 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3894 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3895 .build());
3896 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3897 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3898 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3899 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3900 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3901 .build());
3902
3903 // Move the swipe a bit
3904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3905 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3906 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3907 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3909 .build());
3910
3911 // End the swipe
3912 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3913 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3914 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3915 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3916 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3917 .build());
3918 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3919 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3920 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3921 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3922 .build());
3923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3924 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3925 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3926 .build());
3927
3928 window->assertNoEvents();
3929}
3930
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003931/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003932 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3933 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003934 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003935 */
3936TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3938 sp<FakeWindowHandle> window =
3939 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3940 window->setFrame(Rect(0, 0, 400, 400));
3941 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3942
3943 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3945 .downTime(baseTime + 10)
3946 .eventTime(baseTime + 10)
3947 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3948 .build());
3949
3950 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3951
3952 // We need a new window object for the same window, because dispatcher will store objects by
3953 // reference. That means that the testing code and the dispatcher will refer to the same shared
3954 // object. Calling window->setTransform here would affect dispatcher's comparison
3955 // of the old window to the new window, since both the old window and the new window would be
3956 // updated to the same value.
3957 sp<FakeWindowHandle> windowDup = window->duplicate();
3958
3959 // Change the transform so that the orientation is now different from original.
3960 windowDup->setWindowTransform(0, -1, 1, 0);
3961
3962 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDup}}});
3963
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003964 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3965 .downTime(baseTime + 10)
3966 .eventTime(baseTime + 30)
3967 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3968 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3969 .build());
3970
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003971 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3972
3973 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003974 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3975 .downTime(baseTime + 10)
3976 .eventTime(baseTime + 40)
3977 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3978 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3979 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003980
3981 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3982
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3984 .downTime(baseTime + 10)
3985 .eventTime(baseTime + 50)
3986 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3987 .build());
3988
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003989 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
3990
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3992 .downTime(baseTime + 60)
3993 .eventTime(baseTime + 60)
3994 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
3995 .build());
3996
3997 windowDup->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3998}
3999
4000/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004001 * Ensure the correct coordinate spaces are used by InputDispatcher.
4002 *
4003 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4004 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4005 * space.
4006 */
4007class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4008public:
4009 void SetUp() override {
4010 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004011 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004012 }
4013
4014 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4015 gui::DisplayInfo info;
4016 info.displayId = displayId;
4017 info.transform = transform;
4018 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004019 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004020 }
4021
4022 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4023 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004024 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004025 }
4026
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004027 void removeAllWindowsAndDisplays() {
4028 mDisplayInfos.clear();
4029 mWindowInfos.clear();
4030 }
4031
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004032 // Set up a test scenario where the display has a scaled projection and there are two windows
4033 // on the display.
4034 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4035 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4036 // respectively.
4037 ui::Transform displayTransform;
4038 displayTransform.set(2, 0, 0, 4);
4039 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4040
4041 std::shared_ptr<FakeApplicationHandle> application =
4042 std::make_shared<FakeApplicationHandle>();
4043
4044 // Add two windows to the display. Their frames are represented in the display space.
4045 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004046 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4047 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004048 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4049 addWindow(firstWindow);
4050
4051 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004052 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4053 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004054 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4055 addWindow(secondWindow);
4056 return {std::move(firstWindow), std::move(secondWindow)};
4057 }
4058
4059private:
4060 std::vector<gui::DisplayInfo> mDisplayInfos;
4061 std::vector<gui::WindowInfo> mWindowInfos;
4062};
4063
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004064TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004065 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4066 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004067 // selected so that if the hit test was performed with the point and the bounds being in
4068 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004069 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4070 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4071 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004072
4073 firstWindow->consumeMotionDown();
4074 secondWindow->assertNoEvents();
4075}
4076
4077// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4078// the event should be treated as being in the logical display space.
4079TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4080 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4081 // Send down to the first window. The point is represented in the logical display space. The
4082 // point is selected so that if the hit test was done in logical display space, then it would
4083 // end up in the incorrect window.
4084 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4085 PointF{75 * 2, 55 * 4});
4086
4087 firstWindow->consumeMotionDown();
4088 secondWindow->assertNoEvents();
4089}
4090
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004091// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4092// event should be treated as being in the logical display space.
4093TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4094 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4095
4096 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4097 ui::Transform injectedEventTransform;
4098 injectedEventTransform.set(matrix);
4099 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4100 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4101
4102 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4103 .displayId(ADISPLAY_ID_DEFAULT)
4104 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004105 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004106 .x(untransformedPoint.x)
4107 .y(untransformedPoint.y))
4108 .build();
4109 event.transform(matrix);
4110
4111 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4112 InputEventInjectionSync::WAIT_FOR_RESULT);
4113
4114 firstWindow->consumeMotionDown();
4115 secondWindow->assertNoEvents();
4116}
4117
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004118TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4119 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4120
4121 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004122 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4123 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4124 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004125
4126 firstWindow->assertNoEvents();
4127 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004128 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004129 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4130
4131 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4132 EXPECT_EQ(300, event->getRawX(0));
4133 EXPECT_EQ(880, event->getRawY(0));
4134
4135 // Ensure that the x and y values are in the window's coordinate space.
4136 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4137 // the logical display space. This will be the origin of the window space.
4138 EXPECT_EQ(100, event->getX(0));
4139 EXPECT_EQ(80, event->getY(0));
4140}
4141
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004142/** Ensure consistent behavior of InputDispatcher in all orientations. */
4143class InputDispatcherDisplayOrientationFixture
4144 : public InputDispatcherDisplayProjectionTest,
4145 public ::testing::WithParamInterface<ui::Rotation> {};
4146
4147// This test verifies the touchable region of a window for all rotations of the display by tapping
4148// in different locations on the display, specifically points close to the four corners of a
4149// window.
4150TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4151 constexpr static int32_t displayWidth = 400;
4152 constexpr static int32_t displayHeight = 800;
4153
4154 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4155
4156 const auto rotation = GetParam();
4157
4158 // Set up the display with the specified rotation.
4159 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4160 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4161 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4162 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4163 logicalDisplayWidth, logicalDisplayHeight);
4164 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4165
4166 // Create a window with its bounds determined in the logical display.
4167 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4168 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4169 sp<FakeWindowHandle> window =
4170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4171 window->setFrame(frameInDisplay, displayTransform);
4172 addWindow(window);
4173
4174 // The following points in logical display space should be inside the window.
4175 static const std::array<vec2, 4> insidePoints{
4176 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4177 for (const auto pointInsideWindow : insidePoints) {
4178 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4179 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004180 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4181 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4182 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004183 window->consumeMotionDown();
4184
Prabir Pradhan678438e2023-04-13 19:32:51 +00004185 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4186 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4187 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004188 window->consumeMotionUp();
4189 }
4190
4191 // The following points in logical display space should be outside the window.
4192 static const std::array<vec2, 5> outsidePoints{
4193 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4194 for (const auto pointOutsideWindow : outsidePoints) {
4195 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4196 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004197 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4198 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4199 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004200
Prabir Pradhan678438e2023-04-13 19:32:51 +00004201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4202 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4203 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004204 }
4205 window->assertNoEvents();
4206}
4207
4208// Run the precision tests for all rotations.
4209INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4210 InputDispatcherDisplayOrientationFixture,
4211 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4212 ui::ROTATION_270),
4213 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4214 return ftl::enum_string(testParamInfo.param);
4215 });
4216
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004217using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4218 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004219
4220class TransferTouchFixture : public InputDispatcherTest,
4221 public ::testing::WithParamInterface<TransferFunction> {};
4222
4223TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004225
4226 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004227 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004228 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4229 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004230 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004231 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004232 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4233 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004234 sp<FakeWindowHandle> wallpaper =
4235 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4236 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004237 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004238 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004239
4240 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004241 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4242 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004243
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244 // Only the first window should get the down event
4245 firstWindow->consumeMotionDown();
4246 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004247 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004248
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004249 // Transfer touch to the second window
4250 TransferFunction f = GetParam();
4251 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4252 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004253 // The first window gets cancel and the second gets down
4254 firstWindow->consumeMotionCancel();
4255 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004256 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004257
4258 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004259 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4260 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004261 // The first window gets no events and the second gets up
4262 firstWindow->assertNoEvents();
4263 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004264 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004265}
4266
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004267/**
4268 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4269 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4270 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4271 * natural to the user.
4272 * In this test, we are sending a pointer to both spy window and first window. We then try to
4273 * transfer touch to the second window. The dispatcher should identify the first window as the
4274 * one that should lose the gesture, and therefore the action should be to move the gesture from
4275 * the first window to the second.
4276 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4277 * the other API, as well.
4278 */
4279TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4281
4282 // Create a couple of windows + a spy window
4283 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004284 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004285 spyWindow->setTrustedOverlay(true);
4286 spyWindow->setSpy(true);
4287 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004288 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004289 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004290 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004291
4292 // Add the windows to the dispatcher
4293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4294
4295 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004296 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4297 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004298 // Only the first window and spy should get the down event
4299 spyWindow->consumeMotionDown();
4300 firstWindow->consumeMotionDown();
4301
4302 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4303 // if f === 'transferTouch'.
4304 TransferFunction f = GetParam();
4305 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4306 ASSERT_TRUE(success);
4307 // The first window gets cancel and the second gets down
4308 firstWindow->consumeMotionCancel();
4309 secondWindow->consumeMotionDown();
4310
4311 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004312 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4313 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004314 // The first window gets no events and the second+spy get up
4315 firstWindow->assertNoEvents();
4316 spyWindow->consumeMotionUp();
4317 secondWindow->consumeMotionUp();
4318}
4319
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004320TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004322
4323 PointF touchPoint = {10, 10};
4324
4325 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004326 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004327 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4328 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004329 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004330 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004331 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4332 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004333 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004334
4335 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004337
4338 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004339 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4340 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4341 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004342 // Only the first window should get the down event
4343 firstWindow->consumeMotionDown();
4344 secondWindow->assertNoEvents();
4345
4346 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004347 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4348 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004349 // Only the first window should get the pointer down event
4350 firstWindow->consumeMotionPointerDown(1);
4351 secondWindow->assertNoEvents();
4352
4353 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004354 TransferFunction f = GetParam();
4355 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4356 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004357 // The first window gets cancel and the second gets down and pointer down
4358 firstWindow->consumeMotionCancel();
4359 secondWindow->consumeMotionDown();
4360 secondWindow->consumeMotionPointerDown(1);
4361
4362 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004363 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4364 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004365 // The first window gets nothing and the second gets pointer up
4366 firstWindow->assertNoEvents();
4367 secondWindow->consumeMotionPointerUp(1);
4368
4369 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4371 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004372 // The first window gets nothing and the second gets up
4373 firstWindow->assertNoEvents();
4374 secondWindow->consumeMotionUp();
4375}
4376
Arthur Hungc539dbb2022-12-08 07:45:36 +00004377TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4379
4380 // Create a couple of windows
4381 sp<FakeWindowHandle> firstWindow =
4382 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4383 ADISPLAY_ID_DEFAULT);
4384 firstWindow->setDupTouchToWallpaper(true);
4385 sp<FakeWindowHandle> secondWindow =
4386 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4387 ADISPLAY_ID_DEFAULT);
4388 secondWindow->setDupTouchToWallpaper(true);
4389
4390 sp<FakeWindowHandle> wallpaper1 =
4391 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4392 wallpaper1->setIsWallpaper(true);
4393
4394 sp<FakeWindowHandle> wallpaper2 =
4395 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4396 wallpaper2->setIsWallpaper(true);
4397 // Add the windows to the dispatcher
4398 mDispatcher->setInputWindows(
4399 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4400
4401 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004402 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4403 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004404
4405 // Only the first window should get the down event
4406 firstWindow->consumeMotionDown();
4407 secondWindow->assertNoEvents();
4408 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4409 wallpaper2->assertNoEvents();
4410
4411 // Transfer touch focus to the second window
4412 TransferFunction f = GetParam();
4413 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4414 ASSERT_TRUE(success);
4415
4416 // The first window gets cancel and the second gets down
4417 firstWindow->consumeMotionCancel();
4418 secondWindow->consumeMotionDown();
4419 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4420 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4421
4422 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4424 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004425 // The first window gets no events and the second gets up
4426 firstWindow->assertNoEvents();
4427 secondWindow->consumeMotionUp();
4428 wallpaper1->assertNoEvents();
4429 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4430}
4431
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004432// For the cases of single pointer touch and two pointers non-split touch, the api's
4433// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4434// for the case where there are multiple pointers split across several windows.
4435INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4436 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004437 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4438 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004439 return dispatcher->transferTouch(destChannelToken,
4440 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004441 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004442 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4443 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004444 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004445 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004446 }));
4447
Svet Ganov5d3bc372020-01-26 23:11:07 -08004448TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004450
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004451 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004452 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4453 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004454 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004455
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004456 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004457 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4458 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004459 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004460
4461 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004463
4464 PointF pointInFirst = {300, 200};
4465 PointF pointInSecond = {300, 600};
4466
4467 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004468 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4469 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4470 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004471 // Only the first window should get the down event
4472 firstWindow->consumeMotionDown();
4473 secondWindow->assertNoEvents();
4474
4475 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004476 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4477 ADISPLAY_ID_DEFAULT,
4478 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004479 // The first window gets a move and the second a down
4480 firstWindow->consumeMotionMove();
4481 secondWindow->consumeMotionDown();
4482
4483 // Transfer touch focus to the second window
4484 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4485 // The first window gets cancel and the new gets pointer down (it already saw down)
4486 firstWindow->consumeMotionCancel();
4487 secondWindow->consumeMotionPointerDown(1);
4488
4489 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004490 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4491 ADISPLAY_ID_DEFAULT,
4492 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004493 // The first window gets nothing and the second gets pointer up
4494 firstWindow->assertNoEvents();
4495 secondWindow->consumeMotionPointerUp(1);
4496
4497 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004498 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4499 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004500 // The first window gets nothing and the second gets up
4501 firstWindow->assertNoEvents();
4502 secondWindow->consumeMotionUp();
4503}
4504
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004505// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4506// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4507// touch is not supported, so the touch should continue on those windows and the transferred-to
4508// window should get nothing.
4509TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4511
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004512 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004513 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4514 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004515 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004516
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004517 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004518 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4519 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004520 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004521
4522 // Add the windows to the dispatcher
4523 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4524
4525 PointF pointInFirst = {300, 200};
4526 PointF pointInSecond = {300, 600};
4527
4528 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004529 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4530 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4531 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004532 // Only the first window should get the down event
4533 firstWindow->consumeMotionDown();
4534 secondWindow->assertNoEvents();
4535
4536 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004537 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4538 ADISPLAY_ID_DEFAULT,
4539 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004540 // The first window gets a move and the second a down
4541 firstWindow->consumeMotionMove();
4542 secondWindow->consumeMotionDown();
4543
4544 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004545 const bool transferred =
4546 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004547 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4548 ASSERT_FALSE(transferred);
4549 firstWindow->assertNoEvents();
4550 secondWindow->assertNoEvents();
4551
4552 // The rest of the dispatch should proceed as normal
4553 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004554 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4555 ADISPLAY_ID_DEFAULT,
4556 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004557 // The first window gets MOVE and the second gets pointer up
4558 firstWindow->consumeMotionMove();
4559 secondWindow->consumeMotionUp();
4560
4561 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004562 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4563 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004564 // The first window gets nothing and the second gets up
4565 firstWindow->consumeMotionUp();
4566 secondWindow->assertNoEvents();
4567}
4568
Arthur Hungabbb9d82021-09-01 14:52:30 +00004569// This case will create two windows and one mirrored window on the default display and mirror
4570// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4571// the windows info of second display before default display.
4572TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4573 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4574 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004575 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004576 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004577 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004578 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004579 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004580
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004581 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004582 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004584 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004585 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004587 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004588 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004589
4590 // Update window info, let it find window handle of second display first.
4591 mDispatcher->setInputWindows(
4592 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4593 {ADISPLAY_ID_DEFAULT,
4594 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4595
4596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4597 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4598 {50, 50}))
4599 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4600
4601 // Window should receive motion event.
4602 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4603
4604 // Transfer touch focus
4605 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4606 secondWindowInPrimary->getToken()));
4607 // The first window gets cancel.
4608 firstWindowInPrimary->consumeMotionCancel();
4609 secondWindowInPrimary->consumeMotionDown();
4610
4611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4612 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4613 ADISPLAY_ID_DEFAULT, {150, 50}))
4614 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4615 firstWindowInPrimary->assertNoEvents();
4616 secondWindowInPrimary->consumeMotionMove();
4617
4618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4619 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4620 {150, 50}))
4621 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4622 firstWindowInPrimary->assertNoEvents();
4623 secondWindowInPrimary->consumeMotionUp();
4624}
4625
4626// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4627// 'transferTouch' api.
4628TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4630 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004631 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004632 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004633 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004634 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004635 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004636
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004637 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004638 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004640 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004641 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004643 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004644 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004645
4646 // Update window info, let it find window handle of second display first.
4647 mDispatcher->setInputWindows(
4648 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4649 {ADISPLAY_ID_DEFAULT,
4650 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4651
4652 // Touch on second display.
4653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4654 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4656
4657 // Window should receive motion event.
4658 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4659
4660 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004661 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004662
4663 // The first window gets cancel.
4664 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4665 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4666
4667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4668 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4669 SECOND_DISPLAY_ID, {150, 50}))
4670 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4671 firstWindowInPrimary->assertNoEvents();
4672 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4673
4674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4675 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4677 firstWindowInPrimary->assertNoEvents();
4678 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4679}
4680
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004681TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4684 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004685
Vishnu Nair47074b82020-08-14 11:54:47 -07004686 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004687 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004688 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004689
4690 window->consumeFocusEvent(true);
4691
Prabir Pradhan678438e2023-04-13 19:32:51 +00004692 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004693
4694 // Window should receive key down event.
4695 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004696
4697 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004698 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004699 mFakePolicy->assertUserActivityPoked();
4700}
4701
4702TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4704 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4705 "Fake Window", ADISPLAY_ID_DEFAULT);
4706
4707 window->setDisableUserActivity(true);
4708 window->setFocusable(true);
4709 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4710 setFocusedWindow(window);
4711
4712 window->consumeFocusEvent(true);
4713
4714 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4715
4716 // Window should receive key down event.
4717 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4718
4719 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004720 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004721 mFakePolicy->assertUserActivityNotPoked();
4722}
4723
4724TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4725 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4726 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4727 "Fake Window", ADISPLAY_ID_DEFAULT);
4728
4729 window->setFocusable(true);
4730 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4731 setFocusedWindow(window);
4732
4733 window->consumeFocusEvent(true);
4734
4735 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4736 mDispatcher->waitForIdle();
4737
4738 // System key is not passed down
4739 window->assertNoEvents();
4740
4741 // Should have poked user activity
4742 mFakePolicy->assertUserActivityPoked();
4743}
4744
4745TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4747 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4748 "Fake Window", ADISPLAY_ID_DEFAULT);
4749
4750 window->setFocusable(true);
4751 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4752 setFocusedWindow(window);
4753
4754 window->consumeFocusEvent(true);
4755
4756 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4757 mDispatcher->waitForIdle();
4758
4759 // System key is not passed down
4760 window->assertNoEvents();
4761
4762 // Should have poked user activity
4763 mFakePolicy->assertUserActivityPoked();
4764}
4765
4766TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4769 "Fake Window", ADISPLAY_ID_DEFAULT);
4770
4771 window->setDisableUserActivity(true);
4772 window->setFocusable(true);
4773 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4774 setFocusedWindow(window);
4775
4776 window->consumeFocusEvent(true);
4777
4778 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4779 mDispatcher->waitForIdle();
4780
4781 // System key is not passed down
4782 window->assertNoEvents();
4783
4784 // Should have poked user activity
4785 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004786}
4787
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004788TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4790 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4791 "Fake Window", ADISPLAY_ID_DEFAULT);
4792
4793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4794
4795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4796 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4797 ADISPLAY_ID_DEFAULT, {100, 100}))
4798 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4799
4800 window->consumeMotionEvent(
4801 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4802
4803 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004804 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004805 mFakePolicy->assertUserActivityPoked();
4806}
4807
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004808TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004810 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4811 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004812
Arthur Hung72d8dc32020-03-28 00:48:39 +00004813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004814
Prabir Pradhan678438e2023-04-13 19:32:51 +00004815 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004816 mDispatcher->waitForIdle();
4817
4818 window->assertNoEvents();
4819}
4820
4821// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4822TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004824 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4825 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004826
Arthur Hung72d8dc32020-03-28 00:48:39 +00004827 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004828
4829 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004830 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004831 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004832 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4833 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004834
4835 // Window should receive only the motion event
4836 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4837 window->assertNoEvents(); // Key event or focus event will not be received
4838}
4839
arthurhungea3f4fc2020-12-21 23:18:53 +08004840TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4842
arthurhungea3f4fc2020-12-21 23:18:53 +08004843 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004844 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4845 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004846 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004847
arthurhungea3f4fc2020-12-21 23:18:53 +08004848 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004849 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4850 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004851 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004852
4853 // Add the windows to the dispatcher
4854 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4855
4856 PointF pointInFirst = {300, 200};
4857 PointF pointInSecond = {300, 600};
4858
4859 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004860 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4861 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4862 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004863 // Only the first window should get the down event
4864 firstWindow->consumeMotionDown();
4865 secondWindow->assertNoEvents();
4866
4867 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004868 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4869 ADISPLAY_ID_DEFAULT,
4870 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004871 // The first window gets a move and the second a down
4872 firstWindow->consumeMotionMove();
4873 secondWindow->consumeMotionDown();
4874
4875 // Send pointer cancel to the second window
4876 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004877 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004878 {pointInFirst, pointInSecond});
4879 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004880 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004881 // The first window gets move and the second gets cancel.
4882 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4883 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4884
4885 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004886 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4887 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004888 // The first window gets up and the second gets nothing.
4889 firstWindow->consumeMotionUp();
4890 secondWindow->assertNoEvents();
4891}
4892
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004893TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4895
4896 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004897 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4899 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4900 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4901 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4902
Harry Cutts33476232023-01-30 19:57:29 +00004903 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004904 window->assertNoEvents();
4905 mDispatcher->waitForIdle();
4906}
4907
chaviwd1c23182019-12-20 18:44:56 -08004908class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004909public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004910 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004911 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004912 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004913 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004914 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004915 }
4916
chaviwd1c23182019-12-20 18:44:56 -08004917 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4918
4919 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004920 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4921 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004922 }
4923
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004924 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4925
4926 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4927
chaviwd1c23182019-12-20 18:44:56 -08004928 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004929 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004930 expectedDisplayId, expectedFlags);
4931 }
4932
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004933 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004934 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004935 expectedDisplayId, expectedFlags);
4936 }
4937
chaviwd1c23182019-12-20 18:44:56 -08004938 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004939 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004940 expectedDisplayId, expectedFlags);
4941 }
4942
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004943 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004944 mInputReceiver->consumeMotionEvent(
4945 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4946 WithDisplayId(expectedDisplayId),
4947 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004948 }
4949
Arthur Hungfbfa5722021-11-16 02:45:54 +00004950 void consumeMotionPointerDown(int32_t pointerIdx) {
4951 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4952 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004953 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004954 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004955 }
4956
Evan Rosky84f07f02021-04-16 10:42:42 -07004957 MotionEvent* consumeMotion() {
4958 InputEvent* event = mInputReceiver->consume();
4959 if (!event) {
4960 ADD_FAILURE() << "No event was produced";
4961 return nullptr;
4962 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004963 if (event->getType() != InputEventType::MOTION) {
4964 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004965 return nullptr;
4966 }
4967 return static_cast<MotionEvent*>(event);
4968 }
4969
chaviwd1c23182019-12-20 18:44:56 -08004970 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4971
4972private:
4973 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004974};
4975
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004976using InputDispatcherMonitorTest = InputDispatcherTest;
4977
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004978/**
4979 * Two entities that receive touch: A window, and a global monitor.
4980 * The touch goes to the window, and then the window disappears.
4981 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4982 * for the monitor, as well.
4983 * 1. foregroundWindow
4984 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4985 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004986TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4988 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004989 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004990
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004991 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004992
4993 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4995 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4996 {100, 200}))
4997 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4998
4999 // Both the foreground window and the global monitor should receive the touch down
5000 window->consumeMotionDown();
5001 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5002
5003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5004 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5005 ADISPLAY_ID_DEFAULT, {110, 200}))
5006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5007
5008 window->consumeMotionMove();
5009 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5010
5011 // Now the foreground window goes away
5012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5013 window->consumeMotionCancel();
5014 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5015
5016 // If more events come in, there will be no more foreground window to send them to. This will
5017 // cause a cancel for the monitor, as well.
5018 ASSERT_EQ(InputEventInjectionResult::FAILED,
5019 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5020 ADISPLAY_ID_DEFAULT, {120, 200}))
5021 << "Injection should fail because the window was removed";
5022 window->assertNoEvents();
5023 // Global monitor now gets the cancel
5024 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5025}
5026
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005027TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5030 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005031 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005032
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005033 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005034
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005036 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005038 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005039 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005040}
5041
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005042TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5043 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005044
Chris Yea209fde2020-07-22 13:54:51 -07005045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005046 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5047 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005048 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005049
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005051 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005053 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005054 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005055
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005056 // Pilfer pointers from the monitor.
5057 // This should not do anything and the window should continue to receive events.
5058 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005059
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005061 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5062 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005064
5065 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5066 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005067}
5068
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005069TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005070 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005071 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5072 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005073 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5074 window->setWindowOffset(20, 40);
5075 window->setWindowTransform(0, 1, -1, 0);
5076
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005077 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005078
5079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5080 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5082 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5083 MotionEvent* event = monitor.consumeMotion();
5084 // Even though window has transform, gesture monitor must not.
5085 ASSERT_EQ(ui::Transform(), event->getTransform());
5086}
5087
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005088TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005090 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005091
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005092 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005093 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005094 << "Injection should fail if there is a monitor, but no touchable window";
5095 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005096}
5097
chaviw81e2bb92019-12-18 15:03:51 -08005098TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005100 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5101 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005102
Arthur Hung72d8dc32020-03-28 00:48:39 +00005103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005104
5105 NotifyMotionArgs motionArgs =
5106 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5107 ADISPLAY_ID_DEFAULT);
5108
Prabir Pradhan678438e2023-04-13 19:32:51 +00005109 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005110 // Window should receive motion down event.
5111 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5112
5113 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005114 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005115 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5116 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5117 motionArgs.pointerCoords[0].getX() - 10);
5118
Prabir Pradhan678438e2023-04-13 19:32:51 +00005119 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005120 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005121 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005122}
5123
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005124/**
5125 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5126 * the device default right away. In the test scenario, we check both the default value,
5127 * and the action of enabling / disabling.
5128 */
5129TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005131 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5132 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005133 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005134
5135 // Set focused application.
5136 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005137 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005138
5139 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005141 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005142 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005143
5144 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005145 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005146 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005147 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005148
5149 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005150 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005151 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005152 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005153 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005154 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005155 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005156 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005157
5158 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005159 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005160 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005161 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005162
5163 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005164 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005165 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005166 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005167 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005168 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005169 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005170 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005171
5172 window->assertNoEvents();
5173}
5174
Gang Wange9087892020-01-07 12:17:14 -05005175TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005177 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5178 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005179
5180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005181 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005182
Arthur Hung72d8dc32020-03-28 00:48:39 +00005183 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005184 setFocusedWindow(window);
5185
Harry Cutts33476232023-01-30 19:57:29 +00005186 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005187
Prabir Pradhan678438e2023-04-13 19:32:51 +00005188 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5189 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005190
5191 InputEvent* event = window->consume();
5192 ASSERT_NE(event, nullptr);
5193
5194 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5195 ASSERT_NE(verified, nullptr);
5196 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5197
5198 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5199 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5200 ASSERT_EQ(keyArgs.source, verified->source);
5201 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5202
5203 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5204
5205 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005206 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005207 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005208 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5209 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5210 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5211 ASSERT_EQ(0, verifiedKey.repeatCount);
5212}
5213
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005214TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005215 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005216 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5217 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005218
5219 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5220
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005221 ui::Transform transform;
5222 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5223
5224 gui::DisplayInfo displayInfo;
5225 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5226 displayInfo.transform = transform;
5227
Patrick Williamsd828f302023-04-28 17:52:08 -05005228 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005229
Prabir Pradhan678438e2023-04-13 19:32:51 +00005230 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005231 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5232 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005233 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005234
5235 InputEvent* event = window->consume();
5236 ASSERT_NE(event, nullptr);
5237
5238 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5239 ASSERT_NE(verified, nullptr);
5240 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5241
5242 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5243 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5244 EXPECT_EQ(motionArgs.source, verified->source);
5245 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5246
5247 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5248
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005249 const vec2 rawXY =
5250 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5251 motionArgs.pointerCoords[0].getXYValue());
5252 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5253 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005254 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005255 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005256 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005257 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5258 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5259}
5260
chaviw09c8d2d2020-08-24 15:48:26 -07005261/**
5262 * Ensure that separate calls to sign the same data are generating the same key.
5263 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5264 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5265 * tests.
5266 */
5267TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5268 KeyEvent event = getTestKeyEvent();
5269 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5270
5271 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5272 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5273 ASSERT_EQ(hmac1, hmac2);
5274}
5275
5276/**
5277 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5278 */
5279TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5280 KeyEvent event = getTestKeyEvent();
5281 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5282 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5283
5284 verifiedEvent.deviceId += 1;
5285 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5286
5287 verifiedEvent.source += 1;
5288 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5289
5290 verifiedEvent.eventTimeNanos += 1;
5291 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5292
5293 verifiedEvent.displayId += 1;
5294 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5295
5296 verifiedEvent.action += 1;
5297 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5298
5299 verifiedEvent.downTimeNanos += 1;
5300 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5301
5302 verifiedEvent.flags += 1;
5303 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5304
5305 verifiedEvent.keyCode += 1;
5306 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5307
5308 verifiedEvent.scanCode += 1;
5309 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5310
5311 verifiedEvent.metaState += 1;
5312 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5313
5314 verifiedEvent.repeatCount += 1;
5315 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5316}
5317
Vishnu Nair958da932020-08-21 17:12:37 -07005318TEST_F(InputDispatcherTest, SetFocusedWindow) {
5319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5320 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005321 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005322 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005323 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005324 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5325
5326 // Top window is also focusable but is not granted focus.
5327 windowTop->setFocusable(true);
5328 windowSecond->setFocusable(true);
5329 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5330 setFocusedWindow(windowSecond);
5331
5332 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5334 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005335
5336 // Focused window should receive event.
5337 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5338 windowTop->assertNoEvents();
5339}
5340
5341TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5343 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005344 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005345 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5346
5347 window->setFocusable(true);
5348 // Release channel for window is no longer valid.
5349 window->releaseChannel();
5350 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5351 setFocusedWindow(window);
5352
5353 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005354 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5355 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005356
5357 // window channel is invalid, so it should not receive any input event.
5358 window->assertNoEvents();
5359}
5360
5361TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5362 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5363 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005364 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005365 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005366 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5367
Vishnu Nair958da932020-08-21 17:12:37 -07005368 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5369 setFocusedWindow(window);
5370
5371 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005372 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5373 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005374
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005375 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005376 window->assertNoEvents();
5377}
5378
5379TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5381 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005382 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005383 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005384 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005385 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5386
5387 windowTop->setFocusable(true);
5388 windowSecond->setFocusable(true);
5389 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5390 setFocusedWindow(windowTop);
5391 windowTop->consumeFocusEvent(true);
5392
Chavi Weingarten847e8512023-03-29 00:26:09 +00005393 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005395 windowSecond->consumeFocusEvent(true);
5396 windowTop->consumeFocusEvent(false);
5397
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5399 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005400
5401 // Focused window should receive event.
5402 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5403}
5404
Chavi Weingarten847e8512023-03-29 00:26:09 +00005405TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5407 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005408 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005409 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005410 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005411 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5412
5413 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005414 windowSecond->setFocusable(false);
5415 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005416 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005417 setFocusedWindow(windowTop);
5418 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005419
Chavi Weingarten847e8512023-03-29 00:26:09 +00005420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5421 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005422
5423 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005424 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005425 windowSecond->assertNoEvents();
5426}
5427
5428TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5430 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005431 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005432 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005433 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5434 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005435 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5436
5437 window->setFocusable(true);
5438 previousFocusedWindow->setFocusable(true);
5439 window->setVisible(false);
5440 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5441 setFocusedWindow(previousFocusedWindow);
5442 previousFocusedWindow->consumeFocusEvent(true);
5443
5444 // Requesting focus on invisible window takes focus from currently focused window.
5445 setFocusedWindow(window);
5446 previousFocusedWindow->consumeFocusEvent(false);
5447
5448 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005450 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5451 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005452
5453 // Window does not get focus event or key down.
5454 window->assertNoEvents();
5455
5456 // Window becomes visible.
5457 window->setVisible(true);
5458 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5459
5460 // Window receives focus event.
5461 window->consumeFocusEvent(true);
5462 // Focused window receives key down.
5463 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5464}
5465
Vishnu Nair599f1412021-06-21 10:39:58 -07005466TEST_F(InputDispatcherTest, DisplayRemoved) {
5467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5468 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005469 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005470 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5471
5472 // window is granted focus.
5473 window->setFocusable(true);
5474 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5475 setFocusedWindow(window);
5476 window->consumeFocusEvent(true);
5477
5478 // When a display is removed window loses focus.
5479 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5480 window->consumeFocusEvent(false);
5481}
5482
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005483/**
5484 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5485 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5486 * of the 'slipperyEnterWindow'.
5487 *
5488 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5489 * a way so that the touched location is no longer covered by the top window.
5490 *
5491 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5492 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5493 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5494 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5495 * with ACTION_DOWN).
5496 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5497 * window moved itself away from the touched location and had Flag::SLIPPERY.
5498 *
5499 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5500 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5501 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5502 *
5503 * In this test, we ensure that the event received by the bottom window has
5504 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5505 */
5506TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005507 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005508 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005509
5510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5511 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5512
5513 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005514 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005515 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005516 // Make sure this one overlaps the bottom window
5517 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5518 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5519 // one. Windows with the same owner are not considered to be occluding each other.
5520 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5521
5522 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005523 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005524 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5525
5526 mDispatcher->setInputWindows(
5527 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5528
5529 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5531 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5532 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005533 slipperyExitWindow->consumeMotionDown();
5534 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5535 mDispatcher->setInputWindows(
5536 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5537
Prabir Pradhan678438e2023-04-13 19:32:51 +00005538 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5539 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5540 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005541
5542 slipperyExitWindow->consumeMotionCancel();
5543
5544 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5545 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5546}
5547
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005548/**
5549 * Two windows, one on the left and another on the right. The left window is slippery. The right
5550 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5551 * touch moves from the left window into the right window, the gesture should continue to go to the
5552 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5553 * reproduces a crash.
5554 */
5555TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5557
5558 sp<FakeWindowHandle> leftSlipperyWindow =
5559 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5560 leftSlipperyWindow->setSlippery(true);
5561 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5562
5563 sp<FakeWindowHandle> rightDropTouchesWindow =
5564 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5565 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5566 rightDropTouchesWindow->setDropInput(true);
5567
5568 mDispatcher->setInputWindows(
5569 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5570
5571 // Start touch in the left window
5572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5573 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5574 .build());
5575 leftSlipperyWindow->consumeMotionDown();
5576
5577 // And move it into the right window
5578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5579 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5580 .build());
5581
5582 // Since the right window isn't eligible to receive input, touch does not slip.
5583 // The left window continues to receive the gesture.
5584 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5585 rightDropTouchesWindow->assertNoEvents();
5586}
5587
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005588TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005589 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5591
5592 sp<FakeWindowHandle> leftWindow =
5593 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5594 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005595 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005596
5597 sp<FakeWindowHandle> rightSpy =
5598 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5599 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005600 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005601 rightSpy->setSpy(true);
5602 rightSpy->setTrustedOverlay(true);
5603
5604 sp<FakeWindowHandle> rightWindow =
5605 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5606 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005607 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005608
5609 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5610
5611 // Touch in the left window
5612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5613 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5614 .build());
5615 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5616 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005617 ASSERT_NO_FATAL_FAILURE(
5618 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005619
5620 // Touch another finger over the right windows
5621 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5622 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5623 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5624 .build());
5625 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5626 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5627 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5628 mDispatcher->waitForIdle();
5629 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005630 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5631 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005632
5633 // Release finger over left window. The UP actions are not treated as device interaction.
5634 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5635 // is part of the UP action, we do not treat this as device interaction.
5636 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5637 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5638 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5639 .build());
5640 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5641 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5642 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5643 mDispatcher->waitForIdle();
5644 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5645
5646 // Move remaining finger
5647 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5648 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5649 .build());
5650 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5651 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5652 mDispatcher->waitForIdle();
5653 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005654 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005655
5656 // Release all fingers
5657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5658 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5659 .build());
5660 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5661 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5662 mDispatcher->waitForIdle();
5663 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5664}
5665
5666TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5668
5669 sp<FakeWindowHandle> window =
5670 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5671 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005672 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005673
5674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5675 setFocusedWindow(window);
5676 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5677
5678 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5679 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5680 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005681 ASSERT_NO_FATAL_FAILURE(
5682 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005683
5684 // The UP actions are not treated as device interaction.
5685 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5686 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5687 mDispatcher->waitForIdle();
5688 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5689}
5690
Garfield Tan1c7bc862020-01-28 13:24:04 -08005691class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5692protected:
5693 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5694 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5695
Chris Yea209fde2020-07-22 13:54:51 -07005696 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005697 sp<FakeWindowHandle> mWindow;
5698
5699 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005700 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005701 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005702 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005703 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005704 ASSERT_EQ(OK, mDispatcher->start());
5705
5706 setUpWindow();
5707 }
5708
5709 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005710 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005711 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005712
Vishnu Nair47074b82020-08-14 11:54:47 -07005713 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005714 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005715 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005716 mWindow->consumeFocusEvent(true);
5717 }
5718
Chris Ye2ad95392020-09-01 13:44:44 -07005719 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005720 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005721 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005722 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005723 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005724
5725 // Window should receive key down event.
5726 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5727 }
5728
5729 void expectKeyRepeatOnce(int32_t repeatCount) {
5730 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5731 InputEvent* repeatEvent = mWindow->consume();
5732 ASSERT_NE(nullptr, repeatEvent);
5733
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005734 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005735
5736 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5737 uint32_t eventAction = repeatKeyEvent->getAction();
5738 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5739 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5740 }
5741
Chris Ye2ad95392020-09-01 13:44:44 -07005742 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005743 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005744 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005745 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005746 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005747
5748 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005749 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005750 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005751 }
5752};
5753
5754TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00005755 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005756 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5757 expectKeyRepeatOnce(repeatCount);
5758 }
5759}
5760
5761TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005762 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005763 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5764 expectKeyRepeatOnce(repeatCount);
5765 }
Harry Cutts33476232023-01-30 19:57:29 +00005766 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005767 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005768 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5769 expectKeyRepeatOnce(repeatCount);
5770 }
5771}
5772
5773TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005774 sendAndConsumeKeyDown(/*deviceId=*/1);
5775 expectKeyRepeatOnce(/*repeatCount=*/1);
5776 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005777 mWindow->assertNoEvents();
5778}
5779
5780TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005781 sendAndConsumeKeyDown(/*deviceId=*/1);
5782 expectKeyRepeatOnce(/*repeatCount=*/1);
5783 sendAndConsumeKeyDown(/*deviceId=*/2);
5784 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005785 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005786 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005787 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005788 expectKeyRepeatOnce(/*repeatCount=*/2);
5789 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005790 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005791 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005792 mWindow->assertNoEvents();
5793}
5794
5795TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005796 sendAndConsumeKeyDown(/*deviceId=*/1);
5797 expectKeyRepeatOnce(/*repeatCount=*/1);
5798 sendAndConsumeKeyDown(/*deviceId=*/2);
5799 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005800 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005801 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005802 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005803 mWindow->assertNoEvents();
5804}
5805
liushenxiang42232912021-05-21 20:24:09 +08005806TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5807 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005808 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005809 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005810 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5811 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5812 mWindow->assertNoEvents();
5813}
5814
Garfield Tan1c7bc862020-01-28 13:24:04 -08005815TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005816 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005817 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005818 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5819 InputEvent* repeatEvent = mWindow->consume();
5820 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5821 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5822 IdGenerator::getSource(repeatEvent->getId()));
5823 }
5824}
5825
5826TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005827 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005828 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005829
5830 std::unordered_set<int32_t> idSet;
5831 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5832 InputEvent* repeatEvent = mWindow->consume();
5833 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5834 int32_t id = repeatEvent->getId();
5835 EXPECT_EQ(idSet.end(), idSet.find(id));
5836 idSet.insert(id);
5837 }
5838}
5839
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005840/* Test InputDispatcher for MultiDisplay */
5841class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5842public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005843 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005844 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005845
Chris Yea209fde2020-07-22 13:54:51 -07005846 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005847 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005848 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005849
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005850 // Set focus window for primary display, but focused display would be second one.
5851 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005852 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005853 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005854 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005855 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005856
Chris Yea209fde2020-07-22 13:54:51 -07005857 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005858 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005859 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005860 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005861 // Set focus display to second one.
5862 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5863 // Set focus window for second display.
5864 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005865 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005866 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005867 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005868 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005869 }
5870
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005871 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005872 InputDispatcherTest::TearDown();
5873
Chris Yea209fde2020-07-22 13:54:51 -07005874 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005875 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005876 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005877 windowInSecondary.clear();
5878 }
5879
5880protected:
Chris Yea209fde2020-07-22 13:54:51 -07005881 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005882 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005883 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005884 sp<FakeWindowHandle> windowInSecondary;
5885};
5886
5887TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5888 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5890 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005892 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005893 windowInSecondary->assertNoEvents();
5894
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005895 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5897 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005899 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005900 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005901}
5902
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005903TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005904 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5906 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005907 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005908 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005909 windowInSecondary->assertNoEvents();
5910
5911 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005914 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005915 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005916
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005917 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005918 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005919
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005920 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005921 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005922 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005923
5924 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005925 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005926 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005927 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005928 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005929 windowInSecondary->assertNoEvents();
5930}
5931
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005932// Test per-display input monitors for motion event.
5933TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005934 FakeMonitorReceiver monitorInPrimary =
5935 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5936 FakeMonitorReceiver monitorInSecondary =
5937 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005938
5939 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5941 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5942 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005943 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005944 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005945 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005946 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005947
5948 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5950 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005952 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005953 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005954 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005955 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005956
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005957 // Lift up the touch from the second display
5958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5959 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5960 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5961 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5962 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5963
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005964 // Test inject a non-pointer motion event.
5965 // If specific a display, it will dispatch to the focused window of particular display,
5966 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5968 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5969 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005970 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005971 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005972 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005973 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005974}
5975
5976// Test per-display input monitors for key event.
5977TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005978 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005979 FakeMonitorReceiver monitorInPrimary =
5980 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5981 FakeMonitorReceiver monitorInSecondary =
5982 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005983
5984 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5986 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005987 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005988 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005989 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005990 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005991}
5992
Vishnu Nair958da932020-08-21 17:12:37 -07005993TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
5994 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005995 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005996 secondWindowInPrimary->setFocusable(true);
5997 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
5998 setFocusedWindow(secondWindowInPrimary);
5999 windowInPrimary->consumeFocusEvent(false);
6000 secondWindowInPrimary->consumeFocusEvent(true);
6001
6002 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6004 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006005 windowInPrimary->assertNoEvents();
6006 windowInSecondary->assertNoEvents();
6007 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6008}
6009
Arthur Hungdfd528e2021-12-08 13:23:04 +00006010TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6011 FakeMonitorReceiver monitorInPrimary =
6012 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6013 FakeMonitorReceiver monitorInSecondary =
6014 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6015
6016 // Test touch down on primary display.
6017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6018 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6020 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6021 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6022
6023 // Test touch down on second display.
6024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6025 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6027 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6028 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6029
6030 // Trigger cancel touch.
6031 mDispatcher->cancelCurrentTouch();
6032 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6033 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6034 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6035 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6036
6037 // Test inject a move motion event, no window/monitor should receive the event.
6038 ASSERT_EQ(InputEventInjectionResult::FAILED,
6039 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6040 ADISPLAY_ID_DEFAULT, {110, 200}))
6041 << "Inject motion event should return InputEventInjectionResult::FAILED";
6042 windowInPrimary->assertNoEvents();
6043 monitorInPrimary.assertNoEvents();
6044
6045 ASSERT_EQ(InputEventInjectionResult::FAILED,
6046 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6047 SECOND_DISPLAY_ID, {110, 200}))
6048 << "Inject motion event should return InputEventInjectionResult::FAILED";
6049 windowInSecondary->assertNoEvents();
6050 monitorInSecondary.assertNoEvents();
6051}
6052
Jackal Guof9696682018-10-05 12:23:23 +08006053class InputFilterTest : public InputDispatcherTest {
6054protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006055 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6056 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006057 NotifyMotionArgs motionArgs;
6058
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006059 motionArgs =
6060 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006061 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006062 motionArgs =
6063 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006064 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006065 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006066 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006067 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006068 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006069 } else {
6070 mFakePolicy->assertFilterInputEventWasNotCalled();
6071 }
6072 }
6073
6074 void testNotifyKey(bool expectToBeFiltered) {
6075 NotifyKeyArgs keyArgs;
6076
6077 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006078 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006079 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006080 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006081 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006082
6083 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006084 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006085 } else {
6086 mFakePolicy->assertFilterInputEventWasNotCalled();
6087 }
6088 }
6089};
6090
6091// Test InputFilter for MotionEvent
6092TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6093 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006094 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6095 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006096
6097 // Enable InputFilter
6098 mDispatcher->setInputFilterEnabled(true);
6099 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006100 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6101 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006102
6103 // Disable InputFilter
6104 mDispatcher->setInputFilterEnabled(false);
6105 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006106 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6107 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006108}
6109
6110// Test InputFilter for KeyEvent
6111TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6112 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006113 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006114
6115 // Enable InputFilter
6116 mDispatcher->setInputFilterEnabled(true);
6117 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006118 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006119
6120 // Disable InputFilter
6121 mDispatcher->setInputFilterEnabled(false);
6122 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006123 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006124}
6125
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006126// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6127// logical display coordinate space.
6128TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6129 ui::Transform firstDisplayTransform;
6130 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6131 ui::Transform secondDisplayTransform;
6132 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6133
6134 std::vector<gui::DisplayInfo> displayInfos(2);
6135 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6136 displayInfos[0].transform = firstDisplayTransform;
6137 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6138 displayInfos[1].transform = secondDisplayTransform;
6139
Patrick Williamsd828f302023-04-28 17:52:08 -05006140 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006141
6142 // Enable InputFilter
6143 mDispatcher->setInputFilterEnabled(true);
6144
6145 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006146 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6147 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006148}
6149
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006150class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6151protected:
6152 virtual void SetUp() override {
6153 InputDispatcherTest::SetUp();
6154
6155 /**
6156 * We don't need to enable input filter to test the injected event policy, but we enabled it
6157 * here to make the tests more realistic, since this policy only matters when inputfilter is
6158 * on.
6159 */
6160 mDispatcher->setInputFilterEnabled(true);
6161
6162 std::shared_ptr<InputApplicationHandle> application =
6163 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006164 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6165 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006166
6167 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6168 mWindow->setFocusable(true);
6169 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6170 setFocusedWindow(mWindow);
6171 mWindow->consumeFocusEvent(true);
6172 }
6173
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006174 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6175 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006176 KeyEvent event;
6177
6178 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6179 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6180 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006181 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006182 const int32_t additionalPolicyFlags =
6183 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6184 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006185 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006186 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006187 policyFlags | additionalPolicyFlags));
6188
6189 InputEvent* received = mWindow->consume();
6190 ASSERT_NE(nullptr, received);
6191 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006192 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006193 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6194 ASSERT_EQ(flags, keyEvent.getFlags());
6195 }
6196
6197 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6198 int32_t flags) {
6199 MotionEvent event;
6200 PointerProperties pointerProperties[1];
6201 PointerCoords pointerCoords[1];
6202 pointerProperties[0].clear();
6203 pointerProperties[0].id = 0;
6204 pointerCoords[0].clear();
6205 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6206 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6207
6208 ui::Transform identityTransform;
6209 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6210 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6211 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6212 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6213 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006214 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006215 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006216 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006217
6218 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006220 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006221 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006222 policyFlags | additionalPolicyFlags));
6223
6224 InputEvent* received = mWindow->consume();
6225 ASSERT_NE(nullptr, received);
6226 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006227 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006228 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6229 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006230 }
6231
6232private:
6233 sp<FakeWindowHandle> mWindow;
6234};
6235
6236TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006237 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6238 // filter. Without it, the event will no different from a regularly injected event, and the
6239 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006240 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6241 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006242}
6243
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006244TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006245 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006246 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006247 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6248}
6249
6250TEST_F(InputFilterInjectionPolicyTest,
6251 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6252 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006253 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006254 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006255}
6256
6257TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006258 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6259 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006260}
6261
chaviwfd6d3512019-03-25 13:23:49 -07006262class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006263 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006264 InputDispatcherTest::SetUp();
6265
Chris Yea209fde2020-07-22 13:54:51 -07006266 std::shared_ptr<FakeApplicationHandle> application =
6267 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006268 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006269 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006270 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006271
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006272 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006273 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006274 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006275
6276 // Set focused application.
6277 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006278 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006279
6280 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006282 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006283 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006284 }
6285
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006286 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006287 InputDispatcherTest::TearDown();
6288
6289 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006290 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006291 }
6292
6293protected:
6294 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006295 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006296 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006297};
6298
6299// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6300// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6301// the onPointerDownOutsideFocus callback.
6302TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006304 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6305 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006306 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006307 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006308
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006309 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006310 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6311}
6312
6313// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6314// DOWN on the window that doesn't have focus. Ensure no window received the
6315// onPointerDownOutsideFocus callback.
6316TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006318 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006319 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006320 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006321
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006322 ASSERT_TRUE(mDispatcher->waitForIdle());
6323 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006324}
6325
6326// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6327// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6328TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006329 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6330 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006331 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006332 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006333
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006334 ASSERT_TRUE(mDispatcher->waitForIdle());
6335 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006336}
6337
6338// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6339// DOWN on the window that already has focus. Ensure no window received the
6340// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006341TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006343 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006344 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006345 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006346 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006347
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006348 ASSERT_TRUE(mDispatcher->waitForIdle());
6349 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006350}
6351
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006352// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6353// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6354TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6355 const MotionEvent event =
6356 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6357 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006358 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006359 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6360 .build();
6361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6363 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6364
6365 ASSERT_TRUE(mDispatcher->waitForIdle());
6366 mFakePolicy->assertOnPointerDownWasNotCalled();
6367 // Ensure that the unfocused window did not receive any FOCUS events.
6368 mUnfocusedWindow->assertNoEvents();
6369}
6370
chaviwaf87b3e2019-10-01 16:59:28 -07006371// These tests ensures we can send touch events to a single client when there are multiple input
6372// windows that point to the same client token.
6373class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6374 virtual void SetUp() override {
6375 InputDispatcherTest::SetUp();
6376
Chris Yea209fde2020-07-22 13:54:51 -07006377 std::shared_ptr<FakeApplicationHandle> application =
6378 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006379 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6380 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006381 mWindow1->setFrame(Rect(0, 0, 100, 100));
6382
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006383 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6384 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006385 mWindow2->setFrame(Rect(100, 100, 200, 200));
6386
Arthur Hung72d8dc32020-03-28 00:48:39 +00006387 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006388 }
6389
6390protected:
6391 sp<FakeWindowHandle> mWindow1;
6392 sp<FakeWindowHandle> mWindow2;
6393
6394 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006395 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006396 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6397 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006398 }
6399
6400 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6401 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006402 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006403 InputEvent* event = window->consume();
6404
6405 ASSERT_NE(nullptr, event) << name.c_str()
6406 << ": consumer should have returned non-NULL event.";
6407
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006408 ASSERT_EQ(InputEventType::MOTION, event->getType())
6409 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006410
6411 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006412 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006413 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006414
6415 for (size_t i = 0; i < points.size(); i++) {
6416 float expectedX = points[i].x;
6417 float expectedY = points[i].y;
6418
6419 EXPECT_EQ(expectedX, motionEvent.getX(i))
6420 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6421 << ", got " << motionEvent.getX(i);
6422 EXPECT_EQ(expectedY, motionEvent.getY(i))
6423 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6424 << ", got " << motionEvent.getY(i);
6425 }
6426 }
chaviw9eaa22c2020-07-01 16:21:27 -07006427
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006428 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006429 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006430 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6431 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006432
6433 // Always consume from window1 since it's the window that has the InputReceiver
6434 consumeMotionEvent(mWindow1, action, expectedPoints);
6435 }
chaviwaf87b3e2019-10-01 16:59:28 -07006436};
6437
6438TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6439 // Touch Window 1
6440 PointF touchedPoint = {10, 10};
6441 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006442 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006443
6444 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006445 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006446
6447 // Touch Window 2
6448 touchedPoint = {150, 150};
6449 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006450 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006451}
6452
chaviw9eaa22c2020-07-01 16:21:27 -07006453TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6454 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006455 mWindow2->setWindowScale(0.5f, 0.5f);
6456
6457 // Touch Window 1
6458 PointF touchedPoint = {10, 10};
6459 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006460 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006461 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006462 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006463
6464 // Touch Window 2
6465 touchedPoint = {150, 150};
6466 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006467 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6468 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006469
chaviw9eaa22c2020-07-01 16:21:27 -07006470 // Update the transform so rotation is set
6471 mWindow2->setWindowTransform(0, -1, 1, 0);
6472 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6473 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006474}
6475
chaviw9eaa22c2020-07-01 16:21:27 -07006476TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006477 mWindow2->setWindowScale(0.5f, 0.5f);
6478
6479 // Touch Window 1
6480 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6481 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006482 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006483
6484 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006485 touchedPoints.push_back(PointF{150, 150});
6486 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006487 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006488
chaviw9eaa22c2020-07-01 16:21:27 -07006489 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006490 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006491 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006492
chaviw9eaa22c2020-07-01 16:21:27 -07006493 // Update the transform so rotation is set for Window 2
6494 mWindow2->setWindowTransform(0, -1, 1, 0);
6495 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006496 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006497}
6498
chaviw9eaa22c2020-07-01 16:21:27 -07006499TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006500 mWindow2->setWindowScale(0.5f, 0.5f);
6501
6502 // Touch Window 1
6503 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6504 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006505 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006506
6507 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006508 touchedPoints.push_back(PointF{150, 150});
6509 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006510
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006511 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006512
6513 // Move both windows
6514 touchedPoints = {{20, 20}, {175, 175}};
6515 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6516 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6517
chaviw9eaa22c2020-07-01 16:21:27 -07006518 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006519
chaviw9eaa22c2020-07-01 16:21:27 -07006520 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006521 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006522 expectedPoints.pop_back();
6523
6524 // Touch Window 2
6525 mWindow2->setWindowTransform(0, -1, 1, 0);
6526 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006527 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006528
6529 // Move both windows
6530 touchedPoints = {{20, 20}, {175, 175}};
6531 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6532 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6533
6534 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006535}
6536
6537TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6538 mWindow1->setWindowScale(0.5f, 0.5f);
6539
6540 // Touch Window 1
6541 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6542 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006543 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006544
6545 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006546 touchedPoints.push_back(PointF{150, 150});
6547 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006548
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006549 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006550
6551 // Move both windows
6552 touchedPoints = {{20, 20}, {175, 175}};
6553 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6554 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6555
chaviw9eaa22c2020-07-01 16:21:27 -07006556 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006557}
6558
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006559/**
6560 * When one of the windows is slippery, the touch should not slip into the other window with the
6561 * same input channel.
6562 */
6563TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6564 mWindow1->setSlippery(true);
6565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6566
6567 // Touch down in window 1
6568 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6569 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6570 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6571
6572 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6573 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6574 // getting generated.
6575 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6576 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6577
6578 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6579}
6580
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006581/**
6582 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6583 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6584 * that the pointer is hovering over may have a different transform.
6585 */
6586TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6587 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6588
6589 // Start hover in window 1
6590 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6591 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6592 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6593 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6594
6595 // Move hover to window 2.
6596 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6597 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6598
6599 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6600 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6601 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6602}
6603
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006604class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6605 virtual void SetUp() override {
6606 InputDispatcherTest::SetUp();
6607
Chris Yea209fde2020-07-22 13:54:51 -07006608 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006609 mApplication->setDispatchingTimeout(20ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006610 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6611 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006612 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05006613 mWindow->setDispatchingTimeout(30ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006614 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006615
6616 // Set focused application.
6617 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6618
6619 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006620 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006621 mWindow->consumeFocusEvent(true);
6622 }
6623
6624 virtual void TearDown() override {
6625 InputDispatcherTest::TearDown();
6626 mWindow.clear();
6627 }
6628
6629protected:
Chris Yea209fde2020-07-22 13:54:51 -07006630 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006631 sp<FakeWindowHandle> mWindow;
6632 static constexpr PointF WINDOW_LOCATION = {20, 20};
6633
6634 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006636 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6637 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006639 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6640 WINDOW_LOCATION));
6641 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006642
6643 sp<FakeWindowHandle> addSpyWindow() {
6644 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006645 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006646 spy->setTrustedOverlay(true);
6647 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006648 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006649 spy->setDispatchingTimeout(30ms);
6650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6651 return spy;
6652 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006653};
6654
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006655// Send a tap and respond, which should not cause an ANR.
6656TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6657 tapOnWindow();
6658 mWindow->consumeMotionDown();
6659 mWindow->consumeMotionUp();
6660 ASSERT_TRUE(mDispatcher->waitForIdle());
6661 mFakePolicy->assertNotifyAnrWasNotCalled();
6662}
6663
6664// Send a regular key and respond, which should not cause an ANR.
6665TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006667 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6668 ASSERT_TRUE(mDispatcher->waitForIdle());
6669 mFakePolicy->assertNotifyAnrWasNotCalled();
6670}
6671
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006672TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6673 mWindow->setFocusable(false);
6674 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6675 mWindow->consumeFocusEvent(false);
6676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006677 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006678 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6679 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
6680 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006682 // Key will not go to window because we have no focused window.
6683 // The 'no focused window' ANR timer should start instead.
6684
6685 // Now, the focused application goes away.
6686 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6687 // The key should get dropped and there should be no ANR.
6688
6689 ASSERT_TRUE(mDispatcher->waitForIdle());
6690 mFakePolicy->assertNotifyAnrWasNotCalled();
6691}
6692
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006693// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006694// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6695// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006696TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006698 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6699 WINDOW_LOCATION));
6700
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006701 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6702 ASSERT_TRUE(sequenceNum);
6703 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006704 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006705
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006706 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006707 mWindow->consumeMotionEvent(
6708 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006709 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006710 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006711}
6712
6713// Send a key to the app and have the app not respond right away.
6714TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6715 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006717 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6718 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006719 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006720 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006721 ASSERT_TRUE(mDispatcher->waitForIdle());
6722}
6723
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006724// We have a focused application, but no focused window
6725TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006726 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6728 mWindow->consumeFocusEvent(false);
6729
6730 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006732 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6733 WINDOW_LOCATION));
6734 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6735 mDispatcher->waitForIdle();
6736 mFakePolicy->assertNotifyAnrWasNotCalled();
6737
6738 // Once a focused event arrives, we get an ANR for this application
6739 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6740 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006741 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006742 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6743 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006744 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006745 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006746 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006747 ASSERT_TRUE(mDispatcher->waitForIdle());
6748}
6749
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006750/**
6751 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6752 * there will not be an ANR.
6753 */
6754TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6755 mWindow->setFocusable(false);
6756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6757 mWindow->consumeFocusEvent(false);
6758
6759 KeyEvent event;
6760 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6761 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6762
6763 // Define a valid key down event that is stale (too old).
6764 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006765 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006766 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006767
6768 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6769
6770 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006772 InputEventInjectionSync::WAIT_FOR_RESULT,
6773 INJECT_EVENT_TIMEOUT, policyFlags);
6774 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6775 << "Injection should fail because the event is stale";
6776
6777 ASSERT_TRUE(mDispatcher->waitForIdle());
6778 mFakePolicy->assertNotifyAnrWasNotCalled();
6779 mWindow->assertNoEvents();
6780}
6781
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006782// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006783// Make sure that we don't notify policy twice about the same ANR.
6784TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006785 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006786 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6787 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006788
6789 // Once a focused event arrives, we get an ANR for this application
6790 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6791 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006792 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006793 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
6794 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006795 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006796 const std::chrono::duration appTimeout =
6797 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6798 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006799
Vishnu Naire4df8752022-09-08 09:17:55 -07006800 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006801 // ANR should not be raised again. It is up to policy to do that if it desires.
6802 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006803
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006804 // If we now get a focused window, the ANR should stop, but the policy handles that via
6805 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806 ASSERT_TRUE(mDispatcher->waitForIdle());
6807}
6808
6809// We have a focused application, but no focused window
6810TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
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 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006816 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006817 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006818 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
6819 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006820
Vishnu Naire4df8752022-09-08 09:17:55 -07006821 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6822 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006823
6824 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006825 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006826 ASSERT_TRUE(mDispatcher->waitForIdle());
6827 mWindow->assertNoEvents();
6828}
6829
6830/**
6831 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6832 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6833 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6834 * the ANR mechanism should still work.
6835 *
6836 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6837 * DOWN event, while not responding on the second one.
6838 */
6839TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6840 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6841 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6842 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6843 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6844 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006845 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006846
6847 // Now send ACTION_UP, with identical timestamp
6848 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6849 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6850 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6851 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006852 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006853
6854 // We have now sent down and up. Let's consume first event and then ANR on the second.
6855 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6856 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006857 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006858}
6859
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006860// A spy window can receive an ANR
6861TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6862 sp<FakeWindowHandle> spy = addSpyWindow();
6863
6864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6865 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6866 WINDOW_LOCATION));
6867 mWindow->consumeMotionDown();
6868
6869 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6870 ASSERT_TRUE(sequenceNum);
6871 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006872 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006873
6874 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006875 spy->consumeMotionEvent(
6876 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006877 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006878 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006879}
6880
6881// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006882// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006883TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6884 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006885
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6887 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006888 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006890
6891 // Stuck on the ACTION_UP
6892 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006893 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006894
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006895 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006896 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006897 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6898 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006899
6900 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6901 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006902 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006903 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006904 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006905}
6906
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006907// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006908// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006909TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6910 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006911
6912 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006913 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6914 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006915
6916 mWindow->consumeMotionDown();
6917 // Stuck on the ACTION_UP
6918 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006919 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006920
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006921 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006922 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006923 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6924 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006925
6926 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6927 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006928 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006929 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006930 spy->assertNoEvents();
6931}
6932
6933TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6934 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6935
6936 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6937
6938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6939 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6940 WINDOW_LOCATION));
6941
6942 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6943 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6944 ASSERT_TRUE(consumeSeq);
6945
Prabir Pradhanedd96402022-02-15 01:46:16 -08006946 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006947
6948 monitor.finishEvent(*consumeSeq);
6949 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6950
6951 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006952 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006953}
6954
6955// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6956// process events, you don't get an anr. When the window later becomes unresponsive again, you
6957// get an ANR again.
6958// 1. tap -> block on ACTION_UP -> receive ANR
6959// 2. consume all pending events (= queue becomes healthy again)
6960// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6961TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6962 tapOnWindow();
6963
6964 mWindow->consumeMotionDown();
6965 // Block on ACTION_UP
6966 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006967 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006968 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6969 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006970 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006971 mWindow->assertNoEvents();
6972
6973 tapOnWindow();
6974 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006975 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006976 mWindow->consumeMotionUp();
6977
6978 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006979 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006980 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006981 mWindow->assertNoEvents();
6982}
6983
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006984// If a connection remains unresponsive for a while, make sure policy is only notified once about
6985// it.
6986TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006987 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006988 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6989 WINDOW_LOCATION));
6990
6991 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006992 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006993 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006994 // 'notifyConnectionUnresponsive' should only be called once per connection
6995 mFakePolicy->assertNotifyAnrWasNotCalled();
6996 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006997 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006998 mWindow->consumeMotionEvent(
6999 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007001 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007002 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007003 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007004}
7005
7006/**
7007 * If a window is processing a motion event, and then a key event comes in, the key event should
7008 * not to to the focused window until the motion is processed.
7009 *
7010 * Warning!!!
7011 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7012 * and the injection timeout that we specify when injecting the key.
7013 * We must have the injection timeout (10ms) be smaller than
7014 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7015 *
7016 * If that value changes, this test should also change.
7017 */
7018TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7019 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7020 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7021
7022 tapOnWindow();
7023 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7024 ASSERT_TRUE(downSequenceNum);
7025 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7026 ASSERT_TRUE(upSequenceNum);
7027 // Don't finish the events yet, and send a key
7028 // Injection will "succeed" because we will eventually give up and send the key to the focused
7029 // window even if motions are still being processed. But because the injection timeout is short,
7030 // we will receive INJECTION_TIMED_OUT as the result.
7031
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007032 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007033 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007034 InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
7035 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007036 // Key will not be sent to the window, yet, because the window is still processing events
7037 // and the key remains pending, waiting for the touch events to be processed
7038 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7039 ASSERT_FALSE(keySequenceNum);
7040
7041 std::this_thread::sleep_for(500ms);
7042 // if we wait long enough though, dispatcher will give up, and still send the key
7043 // to the focused window, even though we have not yet finished the motion event
7044 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7045 mWindow->finishEvent(*downSequenceNum);
7046 mWindow->finishEvent(*upSequenceNum);
7047}
7048
7049/**
7050 * If a window is processing a motion event, and then a key event comes in, the key event should
7051 * not go to the focused window until the motion is processed.
7052 * If then a new motion comes in, then the pending key event should be going to the currently
7053 * focused window right away.
7054 */
7055TEST_F(InputDispatcherSingleWindowAnr,
7056 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7057 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7058 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7059
7060 tapOnWindow();
7061 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7062 ASSERT_TRUE(downSequenceNum);
7063 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7064 ASSERT_TRUE(upSequenceNum);
7065 // Don't finish the events yet, and send a key
7066 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007068 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7069 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007070 // At this point, key is still pending, and should not be sent to the application yet.
7071 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7072 ASSERT_FALSE(keySequenceNum);
7073
7074 // Now tap down again. It should cause the pending key to go to the focused window right away.
7075 tapOnWindow();
7076 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7077 // the other events yet. We can finish events in any order.
7078 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7079 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7080 mWindow->consumeMotionDown();
7081 mWindow->consumeMotionUp();
7082 mWindow->assertNoEvents();
7083}
7084
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007085/**
7086 * Send an event to the app and have the app not respond right away.
7087 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7088 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7089 * At some point, the window becomes responsive again.
7090 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7091 */
7092TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7094 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7095 .build());
7096
7097 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7098 ASSERT_TRUE(sequenceNum);
7099 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7100 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7101
7102 mWindow->finishEvent(*sequenceNum);
7103 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7104 ASSERT_TRUE(mDispatcher->waitForIdle());
7105 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7106
7107 // Now that the window is responsive, let's continue the gesture.
7108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7109 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7110 .build());
7111
7112 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7113 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7114 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7115 .build());
7116
7117 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7118 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7119 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7120 .build());
7121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7122 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7123 .build());
7124 // We already canceled this pointer, so the window shouldn't get any new events.
7125 mWindow->assertNoEvents();
7126
7127 // Start another one.
7128 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7129 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7130 .build());
7131 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7132}
7133
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007134class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7135 virtual void SetUp() override {
7136 InputDispatcherTest::SetUp();
7137
Chris Yea209fde2020-07-22 13:54:51 -07007138 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007139 mApplication->setDispatchingTimeout(10ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007140 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7141 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007142 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007143 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007144 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007145
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007146 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7147 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua7d36fd2020-06-30 19:32:39 -05007148 mFocusedWindow->setDispatchingTimeout(30ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007149 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150
7151 // Set focused application.
7152 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007153 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007154
7155 // Expect one focus window exist in display.
7156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007157 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007158 mFocusedWindow->consumeFocusEvent(true);
7159 }
7160
7161 virtual void TearDown() override {
7162 InputDispatcherTest::TearDown();
7163
7164 mUnfocusedWindow.clear();
7165 mFocusedWindow.clear();
7166 }
7167
7168protected:
Chris Yea209fde2020-07-22 13:54:51 -07007169 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007170 sp<FakeWindowHandle> mUnfocusedWindow;
7171 sp<FakeWindowHandle> mFocusedWindow;
7172 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7173 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7174 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7175
7176 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7177
7178 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7179
7180private:
7181 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007183 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7184 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007186 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7187 location));
7188 }
7189};
7190
7191// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7192// should be ANR'd first.
7193TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007195 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7196 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007198 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007199 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007200 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007201 // We consumed all events, so no ANR
7202 ASSERT_TRUE(mDispatcher->waitForIdle());
7203 mFakePolicy->assertNotifyAnrWasNotCalled();
7204
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007206 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7207 FOCUSED_WINDOW_LOCATION));
7208 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7209 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007210
7211 const std::chrono::duration timeout =
7212 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007213 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007214 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7215 // sequence to make it consistent
7216 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007217 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007218 mFocusedWindow->consumeMotionDown();
7219 // This cancel is generated because the connection was unresponsive
7220 mFocusedWindow->consumeMotionCancel();
7221 mFocusedWindow->assertNoEvents();
7222 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007223 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007224 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7225 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007226 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007227}
7228
7229// If we have 2 windows with identical timeouts that are both unresponsive,
7230// it doesn't matter which order they should have ANR.
7231// But we should receive ANR for both.
7232TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7233 // Set the timeout for unfocused window to match the focused window
7234 mUnfocusedWindow->setDispatchingTimeout(10ms);
7235 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7236
7237 tapOnFocusedWindow();
7238 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Prabir Pradhanedd96402022-02-15 01:46:16 -08007239 sp<IBinder> anrConnectionToken1, anrConnectionToken2;
7240 ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms));
7241 ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007242
7243 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007244 ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 ||
7245 mFocusedWindow->getToken() == anrConnectionToken2);
7246 ASSERT_TRUE(mUnfocusedWindow->getToken() == anrConnectionToken1 ||
7247 mUnfocusedWindow->getToken() == anrConnectionToken2);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007248
7249 ASSERT_TRUE(mDispatcher->waitForIdle());
7250 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007251
7252 mFocusedWindow->consumeMotionDown();
7253 mFocusedWindow->consumeMotionUp();
7254 mUnfocusedWindow->consumeMotionOutside();
7255
Prabir Pradhanedd96402022-02-15 01:46:16 -08007256 sp<IBinder> responsiveToken1, responsiveToken2;
7257 ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken());
7258 ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007259
7260 // Both applications should be marked as responsive, in any order
7261 ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 ||
7262 mFocusedWindow->getToken() == responsiveToken2);
7263 ASSERT_TRUE(mUnfocusedWindow->getToken() == responsiveToken1 ||
7264 mUnfocusedWindow->getToken() == responsiveToken2);
7265 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007266}
7267
7268// If a window is already not responding, the second tap on the same window should be ignored.
7269// We should also log an error to account for the dropped event (not tested here).
7270// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7271TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7272 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007273 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007274 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007275 // Receive the events, but don't respond
7276 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7277 ASSERT_TRUE(downEventSequenceNum);
7278 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7279 ASSERT_TRUE(upEventSequenceNum);
7280 const std::chrono::duration timeout =
7281 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007282 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007283
7284 // Tap once again
7285 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007286 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007287 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7288 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007289 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007290 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7291 FOCUSED_WINDOW_LOCATION));
7292 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7293 // valid touch target
7294 mUnfocusedWindow->assertNoEvents();
7295
7296 // Consume the first tap
7297 mFocusedWindow->finishEvent(*downEventSequenceNum);
7298 mFocusedWindow->finishEvent(*upEventSequenceNum);
7299 ASSERT_TRUE(mDispatcher->waitForIdle());
7300 // The second tap did not go to the focused window
7301 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007302 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007303 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7304 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007305 mFakePolicy->assertNotifyAnrWasNotCalled();
7306}
7307
7308// If you tap outside of all windows, there will not be ANR
7309TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007311 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7312 LOCATION_OUTSIDE_ALL_WINDOWS));
7313 ASSERT_TRUE(mDispatcher->waitForIdle());
7314 mFakePolicy->assertNotifyAnrWasNotCalled();
7315}
7316
7317// Since the focused window is paused, tapping on it should not produce any events
7318TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7319 mFocusedWindow->setPaused(true);
7320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7321
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007323 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7324 FOCUSED_WINDOW_LOCATION));
7325
7326 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7327 ASSERT_TRUE(mDispatcher->waitForIdle());
7328 // Should not ANR because the window is paused, and touches shouldn't go to it
7329 mFakePolicy->assertNotifyAnrWasNotCalled();
7330
7331 mFocusedWindow->assertNoEvents();
7332 mUnfocusedWindow->assertNoEvents();
7333}
7334
7335/**
7336 * If a window is processing a motion event, and then a key event comes in, the key event should
7337 * not to to the focused window until the motion is processed.
7338 * If a different window becomes focused at this time, the key should go to that window instead.
7339 *
7340 * Warning!!!
7341 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7342 * and the injection timeout that we specify when injecting the key.
7343 * We must have the injection timeout (10ms) be smaller than
7344 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7345 *
7346 * If that value changes, this test should also change.
7347 */
7348TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7349 // Set a long ANR timeout to prevent it from triggering
7350 mFocusedWindow->setDispatchingTimeout(2s);
7351 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7352
7353 tapOnUnfocusedWindow();
7354 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7355 ASSERT_TRUE(downSequenceNum);
7356 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7357 ASSERT_TRUE(upSequenceNum);
7358 // Don't finish the events yet, and send a key
7359 // Injection will succeed because we will eventually give up and send the key to the focused
7360 // window even if motions are still being processed.
7361
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007362 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007363 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7364 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007366 // Key will not be sent to the window, yet, because the window is still processing events
7367 // and the key remains pending, waiting for the touch events to be processed
7368 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7369 ASSERT_FALSE(keySequenceNum);
7370
7371 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007372 mFocusedWindow->setFocusable(false);
7373 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007374 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007375 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007376
7377 // Focus events should precede the key events
7378 mUnfocusedWindow->consumeFocusEvent(true);
7379 mFocusedWindow->consumeFocusEvent(false);
7380
7381 // Finish the tap events, which should unblock dispatcher
7382 mUnfocusedWindow->finishEvent(*downSequenceNum);
7383 mUnfocusedWindow->finishEvent(*upSequenceNum);
7384
7385 // Now that all queues are cleared and no backlog in the connections, the key event
7386 // can finally go to the newly focused "mUnfocusedWindow".
7387 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7388 mFocusedWindow->assertNoEvents();
7389 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007390 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007391}
7392
7393// When the touch stream is split across 2 windows, and one of them does not respond,
7394// then ANR should be raised and the touch should be canceled for the unresponsive window.
7395// The other window should not be affected by that.
7396TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7397 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007398 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7399 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7400 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007401 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007402 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007403
7404 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007405 mDispatcher->notifyMotion(
7406 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7407 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007408
7409 const std::chrono::duration timeout =
7410 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007411 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007412
7413 mUnfocusedWindow->consumeMotionDown();
7414 mFocusedWindow->consumeMotionDown();
7415 // Focused window may or may not receive ACTION_MOVE
7416 // But it should definitely receive ACTION_CANCEL due to the ANR
7417 InputEvent* event;
7418 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7419 ASSERT_TRUE(moveOrCancelSequenceNum);
7420 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7421 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007422 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007423 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7424 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7425 mFocusedWindow->consumeMotionCancel();
7426 } else {
7427 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7428 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007429 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007430 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7431 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007432
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007433 mUnfocusedWindow->assertNoEvents();
7434 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007435 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007436}
7437
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007438/**
7439 * If we have no focused window, and a key comes in, we start the ANR timer.
7440 * The focused application should add a focused window before the timer runs out to prevent ANR.
7441 *
7442 * If the user touches another application during this time, the key should be dropped.
7443 * Next, if a new focused window comes in, without toggling the focused application,
7444 * then no ANR should occur.
7445 *
7446 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7447 * but in some cases the policy may not update the focused application.
7448 */
7449TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7450 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7451 std::make_shared<FakeApplicationHandle>();
7452 focusedApplication->setDispatchingTimeout(60ms);
7453 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7454 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7455 mFocusedWindow->setFocusable(false);
7456
7457 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7458 mFocusedWindow->consumeFocusEvent(false);
7459
7460 // Send a key. The ANR timer should start because there is no focused window.
7461 // 'focusedApplication' will get blamed if this timer completes.
7462 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007463 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007464 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7465 InputEventInjectionSync::NONE, /*injectionTimeout=*/10ms,
7466 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007468
7469 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7470 // then the injected touches won't cause the focused event to get dropped.
7471 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7472 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7473 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7474 // For this test, it means that the key would get delivered to the window once it becomes
7475 // focused.
7476 std::this_thread::sleep_for(10ms);
7477
7478 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007479 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7480 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7481 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007482
7483 // We do not consume the motion right away, because that would require dispatcher to first
7484 // process (== drop) the key event, and by that time, ANR will be raised.
7485 // Set the focused window first.
7486 mFocusedWindow->setFocusable(true);
7487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7488 setFocusedWindow(mFocusedWindow);
7489 mFocusedWindow->consumeFocusEvent(true);
7490 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7491 // to another application. This could be a bug / behaviour in the policy.
7492
7493 mUnfocusedWindow->consumeMotionDown();
7494
7495 ASSERT_TRUE(mDispatcher->waitForIdle());
7496 // Should not ANR because we actually have a focused window. It was just added too slowly.
7497 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7498}
7499
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007500// These tests ensure we cannot send touch events to a window that's positioned behind a window
7501// that has feature NO_INPUT_CHANNEL.
7502// Layout:
7503// Top (closest to user)
7504// mNoInputWindow (above all windows)
7505// mBottomWindow
7506// Bottom (furthest from user)
7507class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7508 virtual void SetUp() override {
7509 InputDispatcherTest::SetUp();
7510
7511 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007512 mNoInputWindow =
7513 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7514 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007515 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007516 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007517 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7518 // It's perfectly valid for this window to not have an associated input channel
7519
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007520 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7521 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007522 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7523
7524 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7525 }
7526
7527protected:
7528 std::shared_ptr<FakeApplicationHandle> mApplication;
7529 sp<FakeWindowHandle> mNoInputWindow;
7530 sp<FakeWindowHandle> mBottomWindow;
7531};
7532
7533TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7534 PointF touchedPoint = {10, 10};
7535
Prabir Pradhan678438e2023-04-13 19:32:51 +00007536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7537 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7538 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007539
7540 mNoInputWindow->assertNoEvents();
7541 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7542 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7543 // and therefore should prevent mBottomWindow from receiving touches
7544 mBottomWindow->assertNoEvents();
7545}
7546
7547/**
7548 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7549 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7550 */
7551TEST_F(InputDispatcherMultiWindowOcclusionTests,
7552 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007553 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7554 "Window with input channel and NO_INPUT_CHANNEL",
7555 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007556
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007557 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007558 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7559 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7560
7561 PointF touchedPoint = {10, 10};
7562
Prabir Pradhan678438e2023-04-13 19:32:51 +00007563 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7564 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7565 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007566
7567 mNoInputWindow->assertNoEvents();
7568 mBottomWindow->assertNoEvents();
7569}
7570
Vishnu Nair958da932020-08-21 17:12:37 -07007571class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7572protected:
7573 std::shared_ptr<FakeApplicationHandle> mApp;
7574 sp<FakeWindowHandle> mWindow;
7575 sp<FakeWindowHandle> mMirror;
7576
7577 virtual void SetUp() override {
7578 InputDispatcherTest::SetUp();
7579 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007580 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7581 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7582 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007583 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7584 mWindow->setFocusable(true);
7585 mMirror->setFocusable(true);
7586 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7587 }
7588};
7589
7590TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7591 // Request focus on a mirrored window
7592 setFocusedWindow(mMirror);
7593
7594 // window gets focused
7595 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7597 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007598 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7599}
7600
7601// A focused & mirrored window remains focused only if the window and its mirror are both
7602// focusable.
7603TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7604 setFocusedWindow(mMirror);
7605
7606 // window gets focused
7607 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7609 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007610 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7612 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007613 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7614
7615 mMirror->setFocusable(false);
7616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7617
7618 // window loses focus since one of the windows associated with the token in not focusable
7619 mWindow->consumeFocusEvent(false);
7620
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007621 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7622 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007623 mWindow->assertNoEvents();
7624}
7625
7626// A focused & mirrored window remains focused until the window and its mirror both become
7627// invisible.
7628TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7629 setFocusedWindow(mMirror);
7630
7631 // window gets focused
7632 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7634 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007635 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7637 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007638 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7639
7640 mMirror->setVisible(false);
7641 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7642
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7644 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007645 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7647 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007648 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7649
7650 mWindow->setVisible(false);
7651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7652
7653 // window loses focus only after all windows associated with the token become invisible.
7654 mWindow->consumeFocusEvent(false);
7655
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007656 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7657 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007658 mWindow->assertNoEvents();
7659}
7660
7661// A focused & mirrored window remains focused until both windows are removed.
7662TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7663 setFocusedWindow(mMirror);
7664
7665 // window gets focused
7666 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7668 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007669 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7671 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007672 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7673
7674 // single window is removed but the window token remains focused
7675 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7678 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007679 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7681 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007682 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7683
7684 // Both windows are removed
7685 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7686 mWindow->consumeFocusEvent(false);
7687
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007688 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7689 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007690 mWindow->assertNoEvents();
7691}
7692
7693// Focus request can be pending until one window becomes visible.
7694TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7695 // Request focus on an invisible mirror.
7696 mWindow->setVisible(false);
7697 mMirror->setVisible(false);
7698 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7699 setFocusedWindow(mMirror);
7700
7701 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007703 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7704 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007705
7706 mMirror->setVisible(true);
7707 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7708
7709 // window gets focused
7710 mWindow->consumeFocusEvent(true);
7711 // window gets the pending key event
7712 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7713}
Prabir Pradhan99987712020-11-10 18:43:05 -08007714
7715class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7716protected:
7717 std::shared_ptr<FakeApplicationHandle> mApp;
7718 sp<FakeWindowHandle> mWindow;
7719 sp<FakeWindowHandle> mSecondWindow;
7720
7721 void SetUp() override {
7722 InputDispatcherTest::SetUp();
7723 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007724 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007725 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007726 mSecondWindow =
7727 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007728 mSecondWindow->setFocusable(true);
7729
7730 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7731 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7732
7733 setFocusedWindow(mWindow);
7734 mWindow->consumeFocusEvent(true);
7735 }
7736
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007737 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007738 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007739 }
7740
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007741 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7742 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007743 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007744 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7745 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007746 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007747 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007748 }
7749};
7750
7751TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7752 // Ensure that capture cannot be obtained for unfocused windows.
7753 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7754 mFakePolicy->assertSetPointerCaptureNotCalled();
7755 mSecondWindow->assertNoEvents();
7756
7757 // Ensure that capture can be enabled from the focus window.
7758 requestAndVerifyPointerCapture(mWindow, true);
7759
7760 // Ensure that capture cannot be disabled from a window that does not have capture.
7761 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7762 mFakePolicy->assertSetPointerCaptureNotCalled();
7763
7764 // Ensure that capture can be disabled from the window with capture.
7765 requestAndVerifyPointerCapture(mWindow, false);
7766}
7767
7768TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007769 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007770
7771 setFocusedWindow(mSecondWindow);
7772
7773 // Ensure that the capture disabled event was sent first.
7774 mWindow->consumeCaptureEvent(false);
7775 mWindow->consumeFocusEvent(false);
7776 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007777 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007778
7779 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007780 notifyPointerCaptureChanged({});
7781 notifyPointerCaptureChanged(request);
7782 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007783 mWindow->assertNoEvents();
7784 mSecondWindow->assertNoEvents();
7785 mFakePolicy->assertSetPointerCaptureNotCalled();
7786}
7787
7788TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007789 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007790
7791 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007792 notifyPointerCaptureChanged({});
7793 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007794
7795 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007796 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007797 mWindow->consumeCaptureEvent(false);
7798 mWindow->assertNoEvents();
7799}
7800
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007801TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7802 requestAndVerifyPointerCapture(mWindow, true);
7803
7804 // The first window loses focus.
7805 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007806 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007807 mWindow->consumeCaptureEvent(false);
7808
7809 // Request Pointer Capture from the second window before the notification from InputReader
7810 // arrives.
7811 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007812 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007813
7814 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007815 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007816
7817 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007818 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007819
7820 mSecondWindow->consumeFocusEvent(true);
7821 mSecondWindow->consumeCaptureEvent(true);
7822}
7823
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007824TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7825 // App repeatedly enables and disables capture.
7826 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7827 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7828 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7829 mFakePolicy->assertSetPointerCaptureCalled(false);
7830 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7831 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7832
7833 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7834 // first request is now stale, this should do nothing.
7835 notifyPointerCaptureChanged(firstRequest);
7836 mWindow->assertNoEvents();
7837
7838 // InputReader notifies that the second request was enabled.
7839 notifyPointerCaptureChanged(secondRequest);
7840 mWindow->consumeCaptureEvent(true);
7841}
7842
Prabir Pradhan7092e262022-05-03 16:51:09 +00007843TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7844 requestAndVerifyPointerCapture(mWindow, true);
7845
7846 // App toggles pointer capture off and on.
7847 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7848 mFakePolicy->assertSetPointerCaptureCalled(false);
7849
7850 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7851 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7852
7853 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7854 // preceding "disable" request.
7855 notifyPointerCaptureChanged(enableRequest);
7856
7857 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7858 // any notifications.
7859 mWindow->assertNoEvents();
7860}
7861
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007862class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7863protected:
7864 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007865
7866 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7867 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7868
7869 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7870 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7871
7872 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7873 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7874 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7875 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7876 MAXIMUM_OBSCURING_OPACITY);
7877
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007878 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7879 static constexpr gui::Uid APP_B_UID{10002};
7880 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007881
7882 sp<FakeWindowHandle> mTouchWindow;
7883
7884 virtual void SetUp() override {
7885 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007886 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007887 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7888 }
7889
7890 virtual void TearDown() override {
7891 InputDispatcherTest::TearDown();
7892 mTouchWindow.clear();
7893 }
7894
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007895 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007896 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007897 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007898 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007899 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007900 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007901 return window;
7902 }
7903
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007904 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007905 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7906 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007907 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007908 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007909 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007910 return window;
7911 }
7912
7913 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007914 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7915 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7916 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007917 }
7918};
7919
7920TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007921 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007922 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007923 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007924
7925 touch();
7926
7927 mTouchWindow->assertNoEvents();
7928}
7929
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007930TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007931 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7932 const sp<FakeWindowHandle>& w =
7933 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7934 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7935
7936 touch();
7937
7938 mTouchWindow->assertNoEvents();
7939}
7940
7941TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007942 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7943 const sp<FakeWindowHandle>& w =
7944 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7945 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7946
7947 touch();
7948
7949 w->assertNoEvents();
7950}
7951
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007952TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007953 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7954 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007955
7956 touch();
7957
7958 mTouchWindow->consumeAnyMotionDown();
7959}
7960
7961TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007962 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007963 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007964 w->setFrame(Rect(0, 0, 50, 50));
7965 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007966
7967 touch({PointF{100, 100}});
7968
7969 mTouchWindow->consumeAnyMotionDown();
7970}
7971
7972TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007973 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007974 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007975 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7976
7977 touch();
7978
7979 mTouchWindow->consumeAnyMotionDown();
7980}
7981
7982TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7983 const sp<FakeWindowHandle>& w =
7984 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7985 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007986
7987 touch();
7988
7989 mTouchWindow->consumeAnyMotionDown();
7990}
7991
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007992TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7993 const sp<FakeWindowHandle>& w =
7994 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7996
7997 touch();
7998
7999 w->assertNoEvents();
8000}
8001
8002/**
8003 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8004 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8005 * window, the occluding window will still receive ACTION_OUTSIDE event.
8006 */
8007TEST_F(InputDispatcherUntrustedTouchesTest,
8008 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8009 const sp<FakeWindowHandle>& w =
8010 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008011 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008012 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8013
8014 touch();
8015
8016 w->consumeMotionOutside();
8017}
8018
8019TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8020 const sp<FakeWindowHandle>& w =
8021 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008022 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008023 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8024
8025 touch();
8026
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008027 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008028}
8029
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008030TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008031 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008032 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8033 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008034 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8035
8036 touch();
8037
8038 mTouchWindow->consumeAnyMotionDown();
8039}
8040
8041TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8042 const sp<FakeWindowHandle>& w =
8043 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8044 MAXIMUM_OBSCURING_OPACITY);
8045 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008046
8047 touch();
8048
8049 mTouchWindow->consumeAnyMotionDown();
8050}
8051
8052TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008053 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008054 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8055 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008056 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8057
8058 touch();
8059
8060 mTouchWindow->assertNoEvents();
8061}
8062
8063TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8064 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8065 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008066 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8067 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008068 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008069 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8070 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008071 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8072
8073 touch();
8074
8075 mTouchWindow->assertNoEvents();
8076}
8077
8078TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8079 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8080 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008081 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8082 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008083 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008084 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8085 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008086 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8087
8088 touch();
8089
8090 mTouchWindow->consumeAnyMotionDown();
8091}
8092
8093TEST_F(InputDispatcherUntrustedTouchesTest,
8094 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8095 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008096 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8097 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008098 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008099 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8100 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008101 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8102
8103 touch();
8104
8105 mTouchWindow->consumeAnyMotionDown();
8106}
8107
8108TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8109 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008110 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8111 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008112 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008113 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8114 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008115 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008116
8117 touch();
8118
8119 mTouchWindow->assertNoEvents();
8120}
8121
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008122TEST_F(InputDispatcherUntrustedTouchesTest,
8123 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8124 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008125 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8126 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008127 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008128 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8129 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8131
8132 touch();
8133
8134 mTouchWindow->assertNoEvents();
8135}
8136
8137TEST_F(InputDispatcherUntrustedTouchesTest,
8138 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8139 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008140 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8141 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008142 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008143 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8144 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8146
8147 touch();
8148
8149 mTouchWindow->consumeAnyMotionDown();
8150}
8151
8152TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8153 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008154 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8155 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008156 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8157
8158 touch();
8159
8160 mTouchWindow->consumeAnyMotionDown();
8161}
8162
8163TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8164 const sp<FakeWindowHandle>& w =
8165 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8166 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8167
8168 touch();
8169
8170 mTouchWindow->consumeAnyMotionDown();
8171}
8172
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008173TEST_F(InputDispatcherUntrustedTouchesTest,
8174 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8175 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8176 const sp<FakeWindowHandle>& w =
8177 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8178 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8179
8180 touch();
8181
8182 mTouchWindow->assertNoEvents();
8183}
8184
8185TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8186 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8187 const sp<FakeWindowHandle>& w =
8188 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8189 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8190
8191 touch();
8192
8193 mTouchWindow->consumeAnyMotionDown();
8194}
8195
8196TEST_F(InputDispatcherUntrustedTouchesTest,
8197 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8198 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8199 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008200 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8201 OPACITY_ABOVE_THRESHOLD);
8202 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8203
8204 touch();
8205
8206 mTouchWindow->consumeAnyMotionDown();
8207}
8208
8209TEST_F(InputDispatcherUntrustedTouchesTest,
8210 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8211 const sp<FakeWindowHandle>& w1 =
8212 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8213 OPACITY_BELOW_THRESHOLD);
8214 const sp<FakeWindowHandle>& w2 =
8215 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8216 OPACITY_BELOW_THRESHOLD);
8217 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8218
8219 touch();
8220
8221 mTouchWindow->assertNoEvents();
8222}
8223
8224/**
8225 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8226 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8227 * (which alone would result in allowing touches) does not affect the blocking behavior.
8228 */
8229TEST_F(InputDispatcherUntrustedTouchesTest,
8230 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8231 const sp<FakeWindowHandle>& wB =
8232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8233 OPACITY_BELOW_THRESHOLD);
8234 const sp<FakeWindowHandle>& wC =
8235 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8236 OPACITY_BELOW_THRESHOLD);
8237 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8238
8239 touch();
8240
8241 mTouchWindow->assertNoEvents();
8242}
8243
8244/**
8245 * This test is testing that a window from a different UID but with same application token doesn't
8246 * block the touch. Apps can share the application token for close UI collaboration for example.
8247 */
8248TEST_F(InputDispatcherUntrustedTouchesTest,
8249 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8250 const sp<FakeWindowHandle>& w =
8251 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8252 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008253 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8254
8255 touch();
8256
8257 mTouchWindow->consumeAnyMotionDown();
8258}
8259
arthurhungb89ccb02020-12-30 16:19:01 +08008260class InputDispatcherDragTests : public InputDispatcherTest {
8261protected:
8262 std::shared_ptr<FakeApplicationHandle> mApp;
8263 sp<FakeWindowHandle> mWindow;
8264 sp<FakeWindowHandle> mSecondWindow;
8265 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008266 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008267 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8268 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008269
8270 void SetUp() override {
8271 InputDispatcherTest::SetUp();
8272 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008273 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008274 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008275
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008276 mSecondWindow =
8277 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008278 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008279
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008280 mSpyWindow =
8281 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008282 mSpyWindow->setSpy(true);
8283 mSpyWindow->setTrustedOverlay(true);
8284 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8285
arthurhungb89ccb02020-12-30 16:19:01 +08008286 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008287 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008288 }
8289
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008290 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8291 switch (fromSource) {
8292 case AINPUT_SOURCE_TOUCHSCREEN:
8293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8294 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8295 ADISPLAY_ID_DEFAULT, {50, 50}))
8296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8297 break;
8298 case AINPUT_SOURCE_STYLUS:
8299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8300 injectMotionEvent(
8301 mDispatcher,
8302 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8303 AINPUT_SOURCE_STYLUS)
8304 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008305 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008306 .x(50)
8307 .y(50))
8308 .build()));
8309 break;
8310 case AINPUT_SOURCE_MOUSE:
8311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8312 injectMotionEvent(
8313 mDispatcher,
8314 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8315 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8316 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008317 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008318 .x(50)
8319 .y(50))
8320 .build()));
8321 break;
8322 default:
8323 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8324 }
arthurhungb89ccb02020-12-30 16:19:01 +08008325
8326 // Window should receive motion event.
8327 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008328 // Spy window should also receive motion event
8329 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008330 }
8331
8332 // Start performing drag, we will create a drag window and transfer touch to it.
8333 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8334 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008335 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008336 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008337 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008338 }
arthurhungb89ccb02020-12-30 16:19:01 +08008339
8340 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008341 mDragWindow =
8342 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008343 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008344 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008345 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008346
8347 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008348 bool transferred =
8349 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008350 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008351 if (transferred) {
8352 mWindow->consumeMotionCancel();
8353 mDragWindow->consumeMotionDown();
8354 }
8355 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008356 }
8357};
8358
8359TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008360 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008361
8362 // Move on window.
8363 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8364 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8365 ADISPLAY_ID_DEFAULT, {50, 50}))
8366 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8367 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8368 mWindow->consumeDragEvent(false, 50, 50);
8369 mSecondWindow->assertNoEvents();
8370
8371 // Move to another window.
8372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8373 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8374 ADISPLAY_ID_DEFAULT, {150, 50}))
8375 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8376 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8377 mWindow->consumeDragEvent(true, 150, 50);
8378 mSecondWindow->consumeDragEvent(false, 50, 50);
8379
8380 // Move back to original window.
8381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8382 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8383 ADISPLAY_ID_DEFAULT, {50, 50}))
8384 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8385 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8386 mWindow->consumeDragEvent(false, 50, 50);
8387 mSecondWindow->consumeDragEvent(true, -50, 50);
8388
8389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8390 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8392 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8393 mWindow->assertNoEvents();
8394 mSecondWindow->assertNoEvents();
8395}
8396
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008397TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008398 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008399
8400 // No cancel event after drag start
8401 mSpyWindow->assertNoEvents();
8402
8403 const MotionEvent secondFingerDownEvent =
8404 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8405 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008406 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8407 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008408 .build();
8409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8410 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8411 InputEventInjectionSync::WAIT_FOR_RESULT))
8412 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8413
8414 // Receives cancel for first pointer after next pointer down
8415 mSpyWindow->consumeMotionCancel();
8416 mSpyWindow->consumeMotionDown();
8417
8418 mSpyWindow->assertNoEvents();
8419}
8420
arthurhungf452d0b2021-01-06 00:19:52 +08008421TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008422 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008423
8424 // Move on window.
8425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8426 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8427 ADISPLAY_ID_DEFAULT, {50, 50}))
8428 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8429 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8430 mWindow->consumeDragEvent(false, 50, 50);
8431 mSecondWindow->assertNoEvents();
8432
8433 // Move to another window.
8434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8435 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8436 ADISPLAY_ID_DEFAULT, {150, 50}))
8437 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8438 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8439 mWindow->consumeDragEvent(true, 150, 50);
8440 mSecondWindow->consumeDragEvent(false, 50, 50);
8441
8442 // drop to another window.
8443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8444 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8445 {150, 50}))
8446 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8447 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008448 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008449 mWindow->assertNoEvents();
8450 mSecondWindow->assertNoEvents();
8451}
8452
arthurhung6d4bed92021-03-17 11:59:33 +08008453TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008454 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008455
8456 // Move on window and keep button pressed.
8457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8458 injectMotionEvent(mDispatcher,
8459 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8460 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008461 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008462 .build()))
8463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8464 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8465 mWindow->consumeDragEvent(false, 50, 50);
8466 mSecondWindow->assertNoEvents();
8467
8468 // Move to another window and release button, expect to drop item.
8469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8470 injectMotionEvent(mDispatcher,
8471 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8472 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008473 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008474 .build()))
8475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8476 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8477 mWindow->assertNoEvents();
8478 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008479 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008480
8481 // nothing to the window.
8482 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8483 injectMotionEvent(mDispatcher,
8484 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8485 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008486 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008487 .build()))
8488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8489 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8490 mWindow->assertNoEvents();
8491 mSecondWindow->assertNoEvents();
8492}
8493
Arthur Hung54745652022-04-20 07:17:41 +00008494TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008495 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008496
8497 // Set second window invisible.
8498 mSecondWindow->setVisible(false);
8499 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8500
8501 // Move on window.
8502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8503 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8504 ADISPLAY_ID_DEFAULT, {50, 50}))
8505 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8506 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8507 mWindow->consumeDragEvent(false, 50, 50);
8508 mSecondWindow->assertNoEvents();
8509
8510 // Move to another window.
8511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8512 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8513 ADISPLAY_ID_DEFAULT, {150, 50}))
8514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8515 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8516 mWindow->consumeDragEvent(true, 150, 50);
8517 mSecondWindow->assertNoEvents();
8518
8519 // drop to another window.
8520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8521 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8522 {150, 50}))
8523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8524 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008525 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008526 mWindow->assertNoEvents();
8527 mSecondWindow->assertNoEvents();
8528}
8529
Arthur Hung54745652022-04-20 07:17:41 +00008530TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008531 // Ensure window could track pointerIds if it didn't support split touch.
8532 mWindow->setPreventSplitting(true);
8533
Arthur Hung54745652022-04-20 07:17:41 +00008534 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8535 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8536 {50, 50}))
8537 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8538 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8539
8540 const MotionEvent secondFingerDownEvent =
8541 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8542 .displayId(ADISPLAY_ID_DEFAULT)
8543 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008544 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8545 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008546 .build();
8547 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8548 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8549 InputEventInjectionSync::WAIT_FOR_RESULT))
8550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008551 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008552
8553 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008554 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008555}
8556
8557TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8558 // First down on second window.
8559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8560 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8561 {150, 50}))
8562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8563
8564 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8565
8566 // Second down on first window.
8567 const MotionEvent secondFingerDownEvent =
8568 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8569 .displayId(ADISPLAY_ID_DEFAULT)
8570 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008571 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8572 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008573 .build();
8574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8575 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8576 InputEventInjectionSync::WAIT_FOR_RESULT))
8577 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8578 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8579
8580 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008581 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008582
8583 // Move on window.
8584 const MotionEvent secondFingerMoveEvent =
8585 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8586 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008587 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8588 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008589 .build();
8590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8591 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8592 InputEventInjectionSync::WAIT_FOR_RESULT));
8593 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8594 mWindow->consumeDragEvent(false, 50, 50);
8595 mSecondWindow->consumeMotionMove();
8596
8597 // Release the drag pointer should perform drop.
8598 const MotionEvent secondFingerUpEvent =
8599 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8600 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008601 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8602 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008603 .build();
8604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8605 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8606 InputEventInjectionSync::WAIT_FOR_RESULT));
8607 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008608 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008609 mWindow->assertNoEvents();
8610 mSecondWindow->consumeMotionMove();
8611}
8612
Arthur Hung3915c1f2022-05-31 07:17:17 +00008613TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008614 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008615
8616 // Update window of second display.
8617 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008618 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008619 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8620
8621 // Let second display has a touch state.
8622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8623 injectMotionEvent(mDispatcher,
8624 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8625 AINPUT_SOURCE_TOUCHSCREEN)
8626 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008627 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008628 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008629 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008630 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008631 // Update window again.
8632 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8633
8634 // Move on window.
8635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8636 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8637 ADISPLAY_ID_DEFAULT, {50, 50}))
8638 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8639 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8640 mWindow->consumeDragEvent(false, 50, 50);
8641 mSecondWindow->assertNoEvents();
8642
8643 // Move to another window.
8644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8645 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8646 ADISPLAY_ID_DEFAULT, {150, 50}))
8647 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8648 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8649 mWindow->consumeDragEvent(true, 150, 50);
8650 mSecondWindow->consumeDragEvent(false, 50, 50);
8651
8652 // drop to another window.
8653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8654 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8655 {150, 50}))
8656 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8657 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008658 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008659 mWindow->assertNoEvents();
8660 mSecondWindow->assertNoEvents();
8661}
8662
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008663TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8664 startDrag(true, AINPUT_SOURCE_MOUSE);
8665 // Move on window.
8666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8667 injectMotionEvent(mDispatcher,
8668 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8669 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8670 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008671 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008672 .x(50)
8673 .y(50))
8674 .build()))
8675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8676 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8677 mWindow->consumeDragEvent(false, 50, 50);
8678 mSecondWindow->assertNoEvents();
8679
8680 // Move to another window.
8681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8682 injectMotionEvent(mDispatcher,
8683 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8684 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8685 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008686 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008687 .x(150)
8688 .y(50))
8689 .build()))
8690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8691 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8692 mWindow->consumeDragEvent(true, 150, 50);
8693 mSecondWindow->consumeDragEvent(false, 50, 50);
8694
8695 // drop to another window.
8696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8697 injectMotionEvent(mDispatcher,
8698 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8699 .buttonState(0)
8700 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008701 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008702 .x(150)
8703 .y(50))
8704 .build()))
8705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8706 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008707 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008708 mWindow->assertNoEvents();
8709 mSecondWindow->assertNoEvents();
8710}
8711
Vishnu Nair062a8672021-09-03 16:07:44 -07008712class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8713
8714TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008716 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8717 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008718 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008719 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8720 window->setFocusable(true);
8721 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8722 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008723 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008724
8725 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008726 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008727 window->assertNoEvents();
8728
Prabir Pradhan678438e2023-04-13 19:32:51 +00008729 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8730 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008731 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8732 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008733 window->assertNoEvents();
8734
8735 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008736 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8738
Prabir Pradhan678438e2023-04-13 19:32:51 +00008739 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008740 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8741
Prabir Pradhan678438e2023-04-13 19:32:51 +00008742 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8743 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008744 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8745 window->assertNoEvents();
8746}
8747
8748TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8749 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8750 std::make_shared<FakeApplicationHandle>();
8751 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008752 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8753 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008754 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008755 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008756 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008758 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8759 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008760 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008761 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008762 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8763 window->setFocusable(true);
8764 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8765 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008766 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008767
8768 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008769 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008770 window->assertNoEvents();
8771
Prabir Pradhan678438e2023-04-13 19:32:51 +00008772 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8773 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008774 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8775 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008776 window->assertNoEvents();
8777
8778 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008779 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008780 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8781
Prabir Pradhan678438e2023-04-13 19:32:51 +00008782 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008783 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8784
Prabir Pradhan678438e2023-04-13 19:32:51 +00008785 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8786 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008787 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8788 window->assertNoEvents();
8789}
8790
8791TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8792 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8793 std::make_shared<FakeApplicationHandle>();
8794 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008795 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8796 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008797 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008798 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008799 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008801 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8802 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008803 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008804 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008805 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8806 window->setFocusable(true);
8807 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8808 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008809 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008810
8811 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008812 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008813 window->assertNoEvents();
8814
Prabir Pradhan678438e2023-04-13 19:32:51 +00008815 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8816 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008817 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8818 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008819 window->assertNoEvents();
8820
8821 // When the window is no longer obscured because it went on top, it should get input
8822 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8823
Prabir Pradhan678438e2023-04-13 19:32:51 +00008824 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008825 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8826
Prabir Pradhan678438e2023-04-13 19:32:51 +00008827 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8828 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008829 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8830 window->assertNoEvents();
8831}
8832
Antonio Kantekf16f2832021-09-28 04:39:20 +00008833class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8834protected:
8835 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008836 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008837 sp<FakeWindowHandle> mWindow;
8838 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008839 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008840
8841 void SetUp() override {
8842 InputDispatcherTest::SetUp();
8843
8844 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008845 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008846 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008847 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008848 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008849 mSecondWindow =
8850 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008851 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008852 mThirdWindow =
8853 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8854 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8855 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008856
8857 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008858 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8859 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8860 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008861 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008862
Antonio Kantek15beb512022-06-13 22:35:41 +00008863 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008864 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008865 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008866 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8867 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008868 mThirdWindow->assertNoEvents();
8869 }
8870
8871 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8872 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008873 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008874 SECOND_DISPLAY_ID)) {
8875 mWindow->assertNoEvents();
8876 mSecondWindow->assertNoEvents();
8877 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008878 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008879 }
8880
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008881 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008882 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008883 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8884 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008885 mWindow->consumeTouchModeEvent(inTouchMode);
8886 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008887 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008888 }
8889};
8890
Antonio Kantek26defcf2022-02-08 01:12:27 +00008891TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008892 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008893 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8894 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008895 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008896}
8897
Antonio Kantek26defcf2022-02-08 01:12:27 +00008898TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8899 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008900 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008901 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008902 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008903 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008904 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008905 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008906 mWindow->assertNoEvents();
8907 mSecondWindow->assertNoEvents();
8908}
8909
8910TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8911 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008912 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008913 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008914 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008915 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008916 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008917}
8918
Antonio Kantekf16f2832021-09-28 04:39:20 +00008919TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008920 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008921 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8922 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008923 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008924 mWindow->assertNoEvents();
8925 mSecondWindow->assertNoEvents();
8926}
8927
Antonio Kantek15beb512022-06-13 22:35:41 +00008928TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8929 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8930 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8931 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008932 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008933 mWindow->assertNoEvents();
8934 mSecondWindow->assertNoEvents();
8935 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8936}
8937
Antonio Kantek48710e42022-03-24 14:19:30 -07008938TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8939 // Interact with the window first.
8940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8941 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8942 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8943
8944 // Then remove focus.
8945 mWindow->setFocusable(false);
8946 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8947
8948 // Assert that caller can switch touch mode by owning one of the last interacted window.
8949 const WindowInfo& windowInfo = *mWindow->getInfo();
8950 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8951 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008952 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008953}
8954
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008955class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8956public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008957 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008958 std::shared_ptr<FakeApplicationHandle> application =
8959 std::make_shared<FakeApplicationHandle>();
8960 std::string name = "Fake Spy ";
8961 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008962 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8963 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008964 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008965 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008966 return spy;
8967 }
8968
8969 sp<FakeWindowHandle> createForeground() {
8970 std::shared_ptr<FakeApplicationHandle> application =
8971 std::make_shared<FakeApplicationHandle>();
8972 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008973 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8974 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008975 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008976 return window;
8977 }
8978
8979private:
8980 int mSpyCount{0};
8981};
8982
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008983using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008984/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008985 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8986 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008987TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
8988 ScopedSilentDeath _silentDeath;
8989
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008990 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008991 spy->setTrustedOverlay(false);
8992 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
8993 ".* not a trusted overlay");
8994}
8995
8996/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008997 * Input injection into a display with a spy window but no foreground windows should succeed.
8998 */
8999TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009000 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9002
9003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9004 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9005 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9006 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9007}
9008
9009/**
9010 * Verify the order in which different input windows receive events. The touched foreground window
9011 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9012 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9013 * receive events before ones belows it.
9014 *
9015 * Here, we set up a scenario with four windows in the following Z order from the top:
9016 * spy1, spy2, window, spy3.
9017 * We then inject an event and verify that the foreground "window" receives it first, followed by
9018 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9019 * window.
9020 */
9021TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9022 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009023 auto spy1 = createSpy();
9024 auto spy2 = createSpy();
9025 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009026 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9027 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9028 const size_t numChannels = channels.size();
9029
Michael Wright8e9a8562022-02-09 13:44:29 +00009030 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009031 if (!epollFd.ok()) {
9032 FAIL() << "Failed to create epoll fd";
9033 }
9034
9035 for (size_t i = 0; i < numChannels; i++) {
9036 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9037 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9038 FAIL() << "Failed to add fd to epoll";
9039 }
9040 }
9041
9042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9043 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9045
9046 std::vector<size_t> eventOrder;
9047 std::vector<struct epoll_event> events(numChannels);
9048 for (;;) {
9049 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9050 (100ms).count());
9051 if (nFds < 0) {
9052 FAIL() << "Failed to call epoll_wait";
9053 }
9054 if (nFds == 0) {
9055 break; // epoll_wait timed out
9056 }
9057 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009058 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009059 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009060 channels[i]->consumeMotionDown();
9061 }
9062 }
9063
9064 // Verify the order in which the events were received.
9065 EXPECT_EQ(3u, eventOrder.size());
9066 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9067 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9068 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9069}
9070
9071/**
9072 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9073 */
9074TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9075 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009076 auto spy = createSpy();
9077 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009078 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9079
9080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9081 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9083 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9084 spy->assertNoEvents();
9085}
9086
9087/**
9088 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9089 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9090 * to the window.
9091 */
9092TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9093 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009094 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009095 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9096 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9097
9098 // Inject an event outside the spy window's touchable region.
9099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9100 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9102 window->consumeMotionDown();
9103 spy->assertNoEvents();
9104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9105 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9107 window->consumeMotionUp();
9108 spy->assertNoEvents();
9109
9110 // Inject an event inside the spy window's touchable region.
9111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9112 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9113 {5, 10}))
9114 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9115 window->consumeMotionDown();
9116 spy->consumeMotionDown();
9117}
9118
9119/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009120 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009121 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009122 */
9123TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9124 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009125 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009126 auto spy = createSpy();
9127 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009128 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009129 spy->setFrame(Rect{0, 0, 20, 20});
9130 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9131
9132 // Inject an event outside the spy window's frame and touchable region.
9133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009134 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9135 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9137 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009138 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009139}
9140
9141/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009142 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9143 * pointers that are down within its bounds.
9144 */
9145TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9146 auto windowLeft = createForeground();
9147 windowLeft->setFrame({0, 0, 100, 200});
9148 auto windowRight = createForeground();
9149 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009150 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009151 spy->setFrame({0, 0, 200, 200});
9152 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9153
9154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9155 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9156 {50, 50}))
9157 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9158 windowLeft->consumeMotionDown();
9159 spy->consumeMotionDown();
9160
9161 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009162 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009163 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009164 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9165 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009166 .build();
9167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9168 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9169 InputEventInjectionSync::WAIT_FOR_RESULT))
9170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9171 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009172 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009173}
9174
9175/**
9176 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9177 * the spy should receive the second pointer with ACTION_DOWN.
9178 */
9179TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9180 auto window = createForeground();
9181 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009182 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009183 spyRight->setFrame({100, 0, 200, 200});
9184 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9185
9186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9187 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9188 {50, 50}))
9189 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9190 window->consumeMotionDown();
9191 spyRight->assertNoEvents();
9192
9193 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009194 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009195 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009196 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9197 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009198 .build();
9199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9200 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9201 InputEventInjectionSync::WAIT_FOR_RESULT))
9202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009203 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009204 spyRight->consumeMotionDown();
9205}
9206
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009207/**
9208 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9209 * windows should be allowed to control split touch.
9210 */
9211TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009212 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009213 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009214 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009215 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009216
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009217 auto window = createForeground();
9218 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009219
9220 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9221
9222 // First finger down, no window touched.
9223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9224 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9225 {100, 200}))
9226 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9227 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9228 window->assertNoEvents();
9229
9230 // Second finger down on window, the window should receive touch down.
9231 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009232 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009233 .displayId(ADISPLAY_ID_DEFAULT)
9234 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009235 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9236 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009237 .build();
9238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9239 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9240 InputEventInjectionSync::WAIT_FOR_RESULT))
9241 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9242
9243 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009244 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009245}
9246
9247/**
9248 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9249 * do not receive key events.
9250 */
9251TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009252 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009253 spy->setFocusable(false);
9254
9255 auto window = createForeground();
9256 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9257 setFocusedWindow(window);
9258 window->consumeFocusEvent(true);
9259
9260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9261 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9262 window->consumeKeyDown(ADISPLAY_ID_NONE);
9263
9264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9265 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9266 window->consumeKeyUp(ADISPLAY_ID_NONE);
9267
9268 spy->assertNoEvents();
9269}
9270
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009271using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9272
9273/**
9274 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9275 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9276 */
9277TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9278 auto window = createForeground();
9279 auto spy1 = createSpy();
9280 auto spy2 = createSpy();
9281 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9282
9283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9284 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9285 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9286 window->consumeMotionDown();
9287 spy1->consumeMotionDown();
9288 spy2->consumeMotionDown();
9289
9290 // Pilfer pointers from the second spy window.
9291 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9292 spy2->assertNoEvents();
9293 spy1->consumeMotionCancel();
9294 window->consumeMotionCancel();
9295
9296 // The rest of the gesture should only be sent to the second spy window.
9297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9298 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9299 ADISPLAY_ID_DEFAULT))
9300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9301 spy2->consumeMotionMove();
9302 spy1->assertNoEvents();
9303 window->assertNoEvents();
9304}
9305
9306/**
9307 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9308 * in the middle of the gesture.
9309 */
9310TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9311 auto window = createForeground();
9312 auto spy = createSpy();
9313 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9314
9315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9316 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9318 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9319 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9320
9321 window->releaseChannel();
9322
9323 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9324
9325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9326 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9328 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9329}
9330
9331/**
9332 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9333 * the spy, but not to any other windows.
9334 */
9335TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9336 auto spy = createSpy();
9337 auto window = createForeground();
9338
9339 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9340
9341 // First finger down on the window and the spy.
9342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9343 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9344 {100, 200}))
9345 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9346 spy->consumeMotionDown();
9347 window->consumeMotionDown();
9348
9349 // Spy window pilfers the pointers.
9350 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9351 window->consumeMotionCancel();
9352
9353 // Second finger down on the window and spy, but the window should not receive the pointer down.
9354 const MotionEvent secondFingerDownEvent =
9355 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9356 .displayId(ADISPLAY_ID_DEFAULT)
9357 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009358 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9359 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009360 .build();
9361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9362 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9363 InputEventInjectionSync::WAIT_FOR_RESULT))
9364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9365
Harry Cutts33476232023-01-30 19:57:29 +00009366 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009367
9368 // Third finger goes down outside all windows, so injection should fail.
9369 const MotionEvent thirdFingerDownEvent =
9370 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9371 .displayId(ADISPLAY_ID_DEFAULT)
9372 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009373 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9374 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9375 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009376 .build();
9377 ASSERT_EQ(InputEventInjectionResult::FAILED,
9378 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9379 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009380 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009381
9382 spy->assertNoEvents();
9383 window->assertNoEvents();
9384}
9385
9386/**
9387 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9388 */
9389TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9390 auto spy = createSpy();
9391 spy->setFrame(Rect(0, 0, 100, 100));
9392 auto window = createForeground();
9393 window->setFrame(Rect(0, 0, 200, 200));
9394
9395 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9396
9397 // First finger down on the window only
9398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9399 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9400 {150, 150}))
9401 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9402 window->consumeMotionDown();
9403
9404 // Second finger down on the spy and window
9405 const MotionEvent secondFingerDownEvent =
9406 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9407 .displayId(ADISPLAY_ID_DEFAULT)
9408 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009409 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9410 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009411 .build();
9412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9413 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9414 InputEventInjectionSync::WAIT_FOR_RESULT))
9415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9416 spy->consumeMotionDown();
9417 window->consumeMotionPointerDown(1);
9418
9419 // Third finger down on the spy and window
9420 const MotionEvent thirdFingerDownEvent =
9421 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9422 .displayId(ADISPLAY_ID_DEFAULT)
9423 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009424 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9425 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9426 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009427 .build();
9428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9429 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9430 InputEventInjectionSync::WAIT_FOR_RESULT))
9431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9432 spy->consumeMotionPointerDown(1);
9433 window->consumeMotionPointerDown(2);
9434
9435 // Spy window pilfers the pointers.
9436 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009437 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9438 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009439
9440 spy->assertNoEvents();
9441 window->assertNoEvents();
9442}
9443
9444/**
9445 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9446 * other windows should be canceled. If this results in the cancellation of all pointers for some
9447 * window, then that window should receive ACTION_CANCEL.
9448 */
9449TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9450 auto spy = createSpy();
9451 spy->setFrame(Rect(0, 0, 100, 100));
9452 auto window = createForeground();
9453 window->setFrame(Rect(0, 0, 200, 200));
9454
9455 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9456
9457 // First finger down on both spy and window
9458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9459 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9460 {10, 10}))
9461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9462 window->consumeMotionDown();
9463 spy->consumeMotionDown();
9464
9465 // Second finger down on the spy and window
9466 const MotionEvent secondFingerDownEvent =
9467 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9468 .displayId(ADISPLAY_ID_DEFAULT)
9469 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009470 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9471 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009472 .build();
9473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9474 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9475 InputEventInjectionSync::WAIT_FOR_RESULT))
9476 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9477 spy->consumeMotionPointerDown(1);
9478 window->consumeMotionPointerDown(1);
9479
9480 // Spy window pilfers the pointers.
9481 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9482 window->consumeMotionCancel();
9483
9484 spy->assertNoEvents();
9485 window->assertNoEvents();
9486}
9487
9488/**
9489 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9490 * be sent to other windows
9491 */
9492TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9493 auto spy = createSpy();
9494 spy->setFrame(Rect(0, 0, 100, 100));
9495 auto window = createForeground();
9496 window->setFrame(Rect(0, 0, 200, 200));
9497
9498 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9499
9500 // First finger down on both window and spy
9501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9502 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9503 {10, 10}))
9504 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9505 window->consumeMotionDown();
9506 spy->consumeMotionDown();
9507
9508 // Spy window pilfers the pointers.
9509 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9510 window->consumeMotionCancel();
9511
9512 // Second finger down on the window only
9513 const MotionEvent secondFingerDownEvent =
9514 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9515 .displayId(ADISPLAY_ID_DEFAULT)
9516 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009517 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9518 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009519 .build();
9520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9521 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9522 InputEventInjectionSync::WAIT_FOR_RESULT))
9523 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9524 window->consumeMotionDown();
9525 window->assertNoEvents();
9526
9527 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9528 spy->consumeMotionMove();
9529 spy->assertNoEvents();
9530}
9531
Prabir Pradhand65552b2021-10-07 11:23:50 -07009532class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9533public:
9534 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9535 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9536 std::make_shared<FakeApplicationHandle>();
9537 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009538 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9539 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009540 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009541 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009542 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009543 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009544 overlay->setTrustedOverlay(true);
9545
9546 std::shared_ptr<FakeApplicationHandle> application =
9547 std::make_shared<FakeApplicationHandle>();
9548 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009549 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9550 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009551 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009552 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009553
9554 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9556 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009557 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009558 return {std::move(overlay), std::move(window)};
9559 }
9560
9561 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009562 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009563 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009564 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009565 }
9566
9567 void sendStylusEvent(int32_t action) {
9568 NotifyMotionArgs motionArgs =
9569 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9570 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009571 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009572 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009573 }
9574};
9575
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009576using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9577
9578TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009579 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009580 ScopedSilentDeath _silentDeath;
9581
Prabir Pradhand65552b2021-10-07 11:23:50 -07009582 auto [overlay, window] = setupStylusOverlayScenario();
9583 overlay->setTrustedOverlay(false);
9584 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9585 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9586 ".* not a trusted overlay");
9587}
9588
9589TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9590 auto [overlay, window] = setupStylusOverlayScenario();
9591 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9592
9593 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9594 overlay->consumeMotionDown();
9595 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9596 overlay->consumeMotionUp();
9597
9598 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9599 window->consumeMotionDown();
9600 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9601 window->consumeMotionUp();
9602
9603 overlay->assertNoEvents();
9604 window->assertNoEvents();
9605}
9606
9607TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9608 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009609 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009610 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9611
9612 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9613 overlay->consumeMotionDown();
9614 window->consumeMotionDown();
9615 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9616 overlay->consumeMotionUp();
9617 window->consumeMotionUp();
9618
9619 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9620 window->consumeMotionDown();
9621 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9622 window->consumeMotionUp();
9623
9624 overlay->assertNoEvents();
9625 window->assertNoEvents();
9626}
9627
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009628/**
9629 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9630 * The scenario is as follows:
9631 * - The stylus interceptor overlay is configured as a spy window.
9632 * - The stylus interceptor spy receives the start of a new stylus gesture.
9633 * - It pilfers pointers and then configures itself to no longer be a spy.
9634 * - The stylus interceptor continues to receive the rest of the gesture.
9635 */
9636TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9637 auto [overlay, window] = setupStylusOverlayScenario();
9638 overlay->setSpy(true);
9639 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9640
9641 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9642 overlay->consumeMotionDown();
9643 window->consumeMotionDown();
9644
9645 // The interceptor pilfers the pointers.
9646 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9647 window->consumeMotionCancel();
9648
9649 // The interceptor configures itself so that it is no longer a spy.
9650 overlay->setSpy(false);
9651 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9652
9653 // It continues to receive the rest of the stylus gesture.
9654 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9655 overlay->consumeMotionMove();
9656 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9657 overlay->consumeMotionUp();
9658
9659 window->assertNoEvents();
9660}
9661
Prabir Pradhan5735a322022-04-11 17:23:34 +00009662struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009663 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009664 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009665 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9666 std::unique_ptr<InputDispatcher>& mDispatcher;
9667
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009668 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009669 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9670
9671 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9672 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9673 ADISPLAY_ID_DEFAULT, {100, 200},
9674 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9675 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9676 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9677 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9678 }
9679
9680 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009681 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009682 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009683 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009684 mPolicyFlags);
9685 }
9686
9687 sp<FakeWindowHandle> createWindow() const {
9688 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9689 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009690 sp<FakeWindowHandle> window =
9691 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9692 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009693 window->setOwnerInfo(mPid, mUid);
9694 return window;
9695 }
9696};
9697
9698using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9699
9700TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009701 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009702 auto window = owner.createWindow();
9703 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9704
9705 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9706 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9707 window->consumeMotionDown();
9708
9709 setFocusedWindow(window);
9710 window->consumeFocusEvent(true);
9711
9712 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9713 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9714 window->consumeKeyDown(ADISPLAY_ID_NONE);
9715}
9716
9717TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009718 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009719 auto window = owner.createWindow();
9720 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9721
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009722 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009723 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9724 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9725
9726 setFocusedWindow(window);
9727 window->consumeFocusEvent(true);
9728
9729 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9730 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9731 window->assertNoEvents();
9732}
9733
9734TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009735 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009736 auto window = owner.createWindow();
9737 auto spy = owner.createWindow();
9738 spy->setSpy(true);
9739 spy->setTrustedOverlay(true);
9740 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9741
9742 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9743 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9744 spy->consumeMotionDown();
9745 window->consumeMotionDown();
9746}
9747
9748TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009749 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009750 auto window = owner.createWindow();
9751
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009752 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009753 auto randosSpy = rando.createWindow();
9754 randosSpy->setSpy(true);
9755 randosSpy->setTrustedOverlay(true);
9756 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9757
9758 // The event is targeted at owner's window, so injection should succeed, but the spy should
9759 // not receive the event.
9760 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9761 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9762 randosSpy->assertNoEvents();
9763 window->consumeMotionDown();
9764}
9765
9766TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009767 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009768 auto window = owner.createWindow();
9769
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009770 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009771 auto randosSpy = rando.createWindow();
9772 randosSpy->setSpy(true);
9773 randosSpy->setTrustedOverlay(true);
9774 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9775
9776 // A user that has injection permission can inject into any window.
9777 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9778 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9779 ADISPLAY_ID_DEFAULT));
9780 randosSpy->consumeMotionDown();
9781 window->consumeMotionDown();
9782
9783 setFocusedWindow(randosSpy);
9784 randosSpy->consumeFocusEvent(true);
9785
9786 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9787 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9788 window->assertNoEvents();
9789}
9790
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009791TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009792 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009793 auto window = owner.createWindow();
9794
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009795 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009796 auto randosWindow = rando.createWindow();
9797 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9798 randosWindow->setWatchOutsideTouch(true);
9799 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9800
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009801 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009802 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9803 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9804 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009805 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009806}
9807
Garfield Tane84e6f92019-08-29 17:28:41 -07009808} // namespace android::inputdispatcher