blob: de6bd149c744128362d63b0de613899a68693be2 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080019
Cody Heiner166a5af2023-07-07 12:25:00 -070020#include <NotifyArgsBuilders.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070021#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080022#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080023#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070024#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070025#include <binder/Binder.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000026#include <fcntl.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080027#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080028#include <gtest/gtest.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100029#include <input/Input.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080030#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080031#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100032
Garfield Tan1c7bc862020-01-28 13:24:04 -080033#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080034#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070035#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080036#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080037#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050040using android::gui::FocusRequest;
41using android::gui::TouchOcclusionMode;
42using android::gui::WindowInfo;
43using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080044using android::os::InputEventInjectionResult;
45using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080046
Garfield Tane84e6f92019-08-29 17:28:41 -070047namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Dominik Laskowski2f01d772022-03-23 16:01:29 -070049using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080050using testing::AllOf;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070051
Michael Wrightd02c5b62014-02-10 15:10:22 -080052// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000053static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
55// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000056static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080057static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Jeff Brownf086ddb2014-02-11 14:28:48 -080059// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000060static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
61static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080062
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000063// Ensure common actions are interchangeable between keys and motions for convenience.
64static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
65static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080066static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
67static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
68static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
69static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070070static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080071static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080072static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080073static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080074/**
75 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
76 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
77 * index 0) is the new pointer going down. The same pointer could have been placed at a different
78 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
79 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
80 * pointer id=0 leaves but the pointer id=1 remains.
81 */
82static constexpr int32_t POINTER_0_DOWN =
83 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080084static constexpr int32_t POINTER_1_DOWN =
85 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000086static constexpr int32_t POINTER_2_DOWN =
87 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000088static constexpr int32_t POINTER_3_DOWN =
89 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +000090static constexpr int32_t POINTER_0_UP =
91 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080092static constexpr int32_t POINTER_1_UP =
93 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +000094static constexpr int32_t POINTER_2_UP =
95 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096
Antonio Kantek15beb512022-06-13 22:35:41 +000097// The default pid and uid for windows created on the primary display by the test.
Prabir 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
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001170 void setTouchable(bool touchable) {
1171 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1172 }
chaviwd1c23182019-12-20 18:44:56 -08001173
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001174 void setFocusable(bool focusable) {
1175 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1176 }
1177
1178 void setVisible(bool visible) {
1179 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1180 }
Vishnu Nair958da932020-08-21 17:12:37 -07001181
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001182 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001183 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001184 }
1185
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001186 void setPaused(bool paused) {
1187 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1188 }
1189
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001190 void setPreventSplitting(bool preventSplitting) {
1191 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 }
1193
1194 void setSlippery(bool slippery) {
1195 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1196 }
1197
1198 void setWatchOutsideTouch(bool watchOutside) {
1199 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1200 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001201
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001202 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1203
1204 void setInterceptsStylus(bool interceptsStylus) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1206 }
1207
1208 void setDropInput(bool dropInput) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1210 }
1211
1212 void setDropInputIfObscured(bool dropInputIfObscured) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1214 }
1215
1216 void setNoInputChannel(bool noInputChannel) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1218 }
1219
Josep del Riob3981622023-04-18 15:49:45 +00001220 void setDisableUserActivity(bool disableUserActivity) {
1221 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1222 }
1223
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001224 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1225
chaviw3277faf2021-05-19 16:45:23 -05001226 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001227
Bernardo Rufino7393d172021-02-26 13:56:11 +00001228 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1229
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001230 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
chaviwd1c23182019-12-20 18:44:56 -08001231 mInfo.frameLeft = frame.left;
1232 mInfo.frameTop = frame.top;
1233 mInfo.frameRight = frame.right;
1234 mInfo.frameBottom = frame.bottom;
1235 mInfo.touchableRegion.clear();
1236 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001237
1238 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1239 ui::Transform translate;
1240 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1241 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001242 }
1243
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001244 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1245
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001246 void setIsWallpaper(bool isWallpaper) {
1247 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1248 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001249
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001250 void setDupTouchToWallpaper(bool hasWallpaper) {
1251 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1252 }
chaviwd1c23182019-12-20 18:44:56 -08001253
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001254 void setTrustedOverlay(bool trustedOverlay) {
1255 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1256 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001257
chaviw9eaa22c2020-07-01 16:21:27 -07001258 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1259 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1260 }
1261
1262 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001263
yunho.shinf4a80b82020-11-16 21:13:57 +09001264 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1265
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001266 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001267 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags);
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001268 }
1269
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001270 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001271 consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, expectedDisplayId, expectedFlags);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001272 }
1273
Svet Ganov5d3bc372020-01-26 23:11:07 -08001274 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001275 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001276 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1277 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001278 }
1279
1280 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001281 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001282 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1283 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001284 }
1285
1286 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001287 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001288 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1289 }
1290
1291 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1292 std::optional<int32_t> expectedFlags = std::nullopt) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001293 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001294 expectedFlags);
1295 }
1296
Svet Ganov5d3bc372020-01-26 23:11:07 -08001297 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001298 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1299 int32_t expectedFlags = 0) {
1300 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1301 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001302 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 }
1304
1305 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001306 int32_t expectedFlags = 0) {
1307 int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
1308 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001309 consumeEvent(InputEventType::MOTION, action, expectedDisplayId, expectedFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08001310 }
1311
1312 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001313 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001314 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP, expectedDisplayId,
Michael Wright3a240c42019-12-10 20:53:41 +00001315 expectedFlags);
1316 }
1317
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001318 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1319 int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001320 consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE, expectedDisplayId,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001321 expectedFlags);
1322 }
1323
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001324 void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1325 int32_t expectedFlags = 0) {
1326 InputEvent* event = consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08001327 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001328 ASSERT_EQ(InputEventType::MOTION, event->getType());
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001329 const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
1330 EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
1331 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getX());
1332 EXPECT_EQ(0.f, motionEvent.getRawPointerCoords(0)->getY());
1333 }
1334
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001335 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1336 ASSERT_NE(mInputReceiver, nullptr)
1337 << "Cannot consume events from a window with no receiver";
1338 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1339 }
1340
Prabir Pradhan99987712020-11-10 18:43:05 -08001341 void consumeCaptureEvent(bool hasCapture) {
1342 ASSERT_NE(mInputReceiver, nullptr)
1343 << "Cannot consume events from a window with no receiver";
1344 mInputReceiver->consumeCaptureEvent(hasCapture);
1345 }
1346
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001347 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
1348 MotionEvent* motionEvent = consumeMotion();
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08001349 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08001350 ASSERT_THAT(*motionEvent, matcher);
1351 }
1352
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001353 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001354 std::optional<int32_t> expectedDisplayId,
1355 std::optional<int32_t> expectedFlags) {
chaviwd1c23182019-12-20 18:44:56 -08001356 ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
1357 mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
1358 expectedFlags);
1359 }
1360
arthurhungb89ccb02020-12-30 16:19:01 +08001361 void consumeDragEvent(bool isExiting, float x, float y) {
1362 mInputReceiver->consumeDragEvent(isExiting, x, y);
1363 }
1364
Antonio Kantekf16f2832021-09-28 04:39:20 +00001365 void consumeTouchModeEvent(bool inTouchMode) {
1366 ASSERT_NE(mInputReceiver, nullptr)
1367 << "Cannot consume events from a window with no receiver";
1368 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1369 }
1370
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001371 std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001372 if (mInputReceiver == nullptr) {
1373 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1374 return std::nullopt;
1375 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001376 return mInputReceiver->receiveEvent(outEvent);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001377 }
1378
1379 void finishEvent(uint32_t sequenceNum) {
1380 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1381 mInputReceiver->finishEvent(sequenceNum);
1382 }
1383
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001384 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1385 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1386 mInputReceiver->sendTimeline(inputEventId, timeline);
1387 }
1388
chaviwaf87b3e2019-10-01 16:59:28 -07001389 InputEvent* consume() {
1390 if (mInputReceiver == nullptr) {
1391 return nullptr;
1392 }
1393 return mInputReceiver->consume();
1394 }
1395
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001396 MotionEvent* consumeMotion() {
1397 InputEvent* event = consume();
1398 if (event == nullptr) {
1399 ADD_FAILURE() << "Consume failed : no event";
1400 return nullptr;
1401 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001402 if (event->getType() != InputEventType::MOTION) {
1403 ADD_FAILURE() << "Instead of motion event, got " << *event;
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00001404 return nullptr;
1405 }
1406 return static_cast<MotionEvent*>(event);
1407 }
1408
Arthur Hungb92218b2018-08-14 12:00:21 +08001409 void assertNoEvents() {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001410 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001411 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001412 return; // Can't receive events if the window does not have input channel
1413 }
1414 ASSERT_NE(nullptr, mInputReceiver)
1415 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
chaviwd1c23182019-12-20 18:44:56 -08001416 mInputReceiver->assertNoEvents();
Arthur Hungb92218b2018-08-14 12:00:21 +08001417 }
1418
chaviwaf87b3e2019-10-01 16:59:28 -07001419 sp<IBinder> getToken() { return mInfo.token; }
1420
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001421 const std::string& getName() { return mName; }
1422
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001423 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001424 mInfo.ownerPid = ownerPid;
1425 mInfo.ownerUid = ownerUid;
1426 }
1427
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001428 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001429
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001430 void destroyReceiver() { mInputReceiver = nullptr; }
1431
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001432 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1433
chaviwd1c23182019-12-20 18:44:56 -08001434private:
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001435 FakeWindowHandle(std::string name) : mName(name){};
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001436 const std::string mName;
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001437 std::shared_ptr<FakeInputReceiver> mInputReceiver;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001438 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001439 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001440};
1441
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001442std::atomic<int32_t> FakeWindowHandle::sId{1};
1443
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001444static InputEventInjectionResult injectKey(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001445 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001446 int32_t displayId = ADISPLAY_ID_NONE,
1447 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001448 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001449 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001450 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001451 KeyEvent event;
1452 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1453
1454 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001455 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001456 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1457 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001458
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001459 if (!allowKeyRepeat) {
1460 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1461 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001462 // Inject event until dispatch out.
Prabir Pradhan5735a322022-04-11 17:23:34 +00001463 return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001464}
1465
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001466static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001467 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001468 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001469}
1470
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001471// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1472// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1473// has to be woken up to process the repeating key.
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001474static InputEventInjectionResult injectKeyDownNoRepeat(
1475 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001476 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001477 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001478 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001479}
1480
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001481static InputEventInjectionResult injectKeyUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001482 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001483 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001484}
1485
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001486static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001487 const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001488 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001489 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001490 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Prabir Pradhan5735a322022-04-11 17:23:34 +00001491 return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1492 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001493}
1494
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001495static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001496 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t action, int32_t source,
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001497 int32_t displayId, const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001498 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001499 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1500 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001501 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001502 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001503 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001504 MotionEventBuilder motionBuilder =
1505 MotionEventBuilder(action, source)
1506 .displayId(displayId)
1507 .eventTime(eventTime)
1508 .rawXCursorPosition(cursorPosition.x)
1509 .rawYCursorPosition(cursorPosition.y)
1510 .pointer(
1511 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1512 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1513 motionBuilder.downTime(eventTime);
1514 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001515
1516 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001517 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1518 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001519}
1520
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001521static InputEventInjectionResult injectMotionDown(
1522 const std::unique_ptr<InputDispatcher>& dispatcher, int32_t source, int32_t displayId,
1523 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001524 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001525}
1526
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001527static InputEventInjectionResult injectMotionUp(const std::unique_ptr<InputDispatcher>& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001528 int32_t source, int32_t displayId,
1529 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001530 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001531}
1532
Jackal Guof9696682018-10-05 12:23:23 +08001533static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1534 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1535 // Define a valid key event.
Harry Cutts33476232023-01-30 19:57:29 +00001536 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001537 displayId, POLICY_FLAG_PASS_TO_USER, action, /*flags=*/0, AKEYCODE_A, KEY_A,
1538 AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001539
1540 return args;
1541}
1542
Josep del Riob3981622023-04-18 15:49:45 +00001543static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1544 int32_t displayId = ADISPLAY_ID_NONE) {
1545 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1546 // Define a valid key event.
1547 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001548 displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C, AMETA_META_ON,
Josep del Riob3981622023-04-18 15:49:45 +00001549 currentTime);
1550
1551 return args;
1552}
1553
1554static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1555 int32_t displayId = ADISPLAY_ID_NONE) {
1556 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1557 // Define a valid key event.
1558 NotifyKeyArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001559 displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST, KEY_ASSISTANT,
Josep del Riob3981622023-04-18 15:49:45 +00001560 AMETA_NONE, currentTime);
1561
1562 return args;
1563}
1564
Prabir Pradhan678438e2023-04-13 19:32:51 +00001565[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1566 int32_t displayId,
1567 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001568 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001569 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1570 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1571 }
1572
chaviwd1c23182019-12-20 18:44:56 -08001573 PointerProperties pointerProperties[pointerCount];
1574 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001575
chaviwd1c23182019-12-20 18:44:56 -08001576 for (size_t i = 0; i < pointerCount; i++) {
1577 pointerProperties[i].clear();
1578 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001579 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001580
chaviwd1c23182019-12-20 18:44:56 -08001581 pointerCoords[i].clear();
1582 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1583 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1584 }
Jackal Guof9696682018-10-05 12:23:23 +08001585
1586 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1587 // Define a valid motion event.
Harry Cutts33476232023-01-30 19:57:29 +00001588 NotifyMotionArgs args(/*id=*/0, currentTime, /*readTime=*/0, DEVICE_ID, source, displayId,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001589 POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0, /*flags=*/0,
1590 AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001591 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001592 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001593 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001594 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001595
1596 return args;
1597}
1598
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001599static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1600 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1601}
1602
chaviwd1c23182019-12-20 18:44:56 -08001603static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1604 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1605}
1606
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001607static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1608 const PointerCaptureRequest& request) {
Harry Cutts33476232023-01-30 19:57:29 +00001609 return NotifyPointerCaptureChangedArgs(/*id=*/0, systemTime(SYSTEM_TIME_MONOTONIC), request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001610}
1611
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001612} // namespace
1613
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001614/**
1615 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1616 * broken channel.
1617 */
1618TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1620 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001621 sp<FakeWindowHandle>::make(application, mDispatcher,
1622 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001623
1624 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1625
1626 // Window closes its channel, but the window remains.
1627 window->destroyReceiver();
1628 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1629}
1630
Arthur Hungb92218b2018-08-14 12:00:21 +08001631TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001632 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001633 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1634 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001635
Arthur Hung72d8dc32020-03-28 00:48:39 +00001636 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1638 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001640
1641 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001642 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001643}
1644
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001645TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001647 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1648 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001649
1650 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1651 // Inject a MotionEvent to an unknown display.
1652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1653 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
1654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1655
1656 // Window should receive motion event.
1657 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1658}
1659
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001660/**
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001661 * Calling setInputWindows once should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001662 * This test serves as a sanity check for the next test, where setInputWindows is
1663 * called twice.
1664 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001665TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001666 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001667 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1668 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001669 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001670
1671 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001673 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1674 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001676
1677 // Window should receive motion event.
1678 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1679}
1680
1681/**
1682 * Calling setInputWindows twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001683 */
1684TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1687 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001688 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001689
1690 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
1691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001693 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1694 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001696
1697 // Window should receive motion event.
1698 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1699}
1700
Arthur Hungb92218b2018-08-14 12:00:21 +08001701// The foreground window should receive the first touch down event.
1702TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001704 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001705 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001706 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001707 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001708
Arthur Hung72d8dc32020-03-28 00:48:39 +00001709 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1711 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
1712 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001713
1714 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001715 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001716 windowSecond->assertNoEvents();
1717}
1718
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001719/**
1720 * Two windows: A top window, and a wallpaper behind the window.
1721 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1722 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001723 * 1. foregroundWindow <-- dup touch to wallpaper
1724 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001725 */
1726TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1728 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001729 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001730 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001731 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001732 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001733 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001734
1735 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1737 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1738 {100, 200}))
1739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1740
1741 // Both foreground window and its wallpaper should receive the touch down
1742 foregroundWindow->consumeMotionDown();
1743 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1744
1745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1746 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1747 ADISPLAY_ID_DEFAULT, {110, 200}))
1748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1749
1750 foregroundWindow->consumeMotionMove();
1751 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1752
1753 // Now the foreground window goes away, but the wallpaper stays
1754 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1755 foregroundWindow->consumeMotionCancel();
1756 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1757 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1758}
1759
1760/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001761 * Two fingers down on the window, and lift off the first finger.
1762 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1763 * contains a single pointer.
1764 */
1765TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1767 sp<FakeWindowHandle> window =
1768 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1769
1770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001771 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1773 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1774 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001775 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001776 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1777 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1778 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1779 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001780 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001781 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1782 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1783 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1784 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001785 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1786 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1787 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1788
1789 // Remove the window. The gesture should be canceled
1790 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
1791 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1792 window->consumeMotionEvent(
1793 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1794}
1795
1796/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001797 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1798 * with the following differences:
1799 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1800 * clean up the connection.
1801 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1802 * Ensure that there's no crash in the dispatcher.
1803 */
1804TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1806 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001807 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001808 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001809 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001810 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001811 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001812
1813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
1814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1815 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1816 {100, 200}))
1817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1818
1819 // Both foreground window and its wallpaper should receive the touch down
1820 foregroundWindow->consumeMotionDown();
1821 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1822
1823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1824 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
1825 ADISPLAY_ID_DEFAULT, {110, 200}))
1826 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1827
1828 foregroundWindow->consumeMotionMove();
1829 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1830
1831 // Wallpaper closes its channel, but the window remains.
1832 wallpaperWindow->destroyReceiver();
1833 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1834
1835 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1836 // is no longer valid.
1837 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wallpaperWindow}}});
1838 foregroundWindow->consumeMotionCancel();
1839}
1840
Arthur Hungc539dbb2022-12-08 07:45:36 +00001841class ShouldSplitTouchFixture : public InputDispatcherTest,
1842 public ::testing::WithParamInterface<bool> {};
1843INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1844 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001845/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001846 * A single window that receives touch (on top), and a wallpaper window underneath it.
1847 * The top window gets a multitouch gesture.
1848 * Ensure that wallpaper gets the same gesture.
1849 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001850TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001852 sp<FakeWindowHandle> foregroundWindow =
1853 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1854 foregroundWindow->setDupTouchToWallpaper(true);
1855 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001856
1857 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001858 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001859 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001860
Arthur Hungc539dbb2022-12-08 07:45:36 +00001861 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {foregroundWindow, wallpaperWindow}}});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001862
1863 // Touch down on top window
1864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1865 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1866 {100, 100}))
1867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1868
1869 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001870 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001871 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1872
1873 // Second finger down on the top window
1874 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001875 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001876 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001877 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1878 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879 .build();
1880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1881 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1882 InputEventInjectionSync::WAIT_FOR_RESULT))
1883 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1884
Harry Cutts33476232023-01-30 19:57:29 +00001885 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1886 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001887 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001888
1889 const MotionEvent secondFingerUpEvent =
1890 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1891 .displayId(ADISPLAY_ID_DEFAULT)
1892 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001893 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1894 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001895 .build();
1896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1897 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
1898 InputEventInjectionSync::WAIT_FOR_RESULT))
1899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1900 foregroundWindow->consumeMotionPointerUp(0);
1901 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1902
1903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001904 injectMotionEvent(mDispatcher,
1905 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1906 AINPUT_SOURCE_TOUCHSCREEN)
1907 .displayId(ADISPLAY_ID_DEFAULT)
1908 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001909 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001910 .x(100)
1911 .y(100))
1912 .build(),
1913 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1915 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1916 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001917}
1918
1919/**
1920 * Two windows: a window on the left and window on the right.
1921 * A third window, wallpaper, is behind both windows, and spans both top windows.
1922 * The first touch down goes to the left window. A second pointer touches down on the right window.
1923 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1924 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1925 * ACTION_POINTER_DOWN(1).
1926 */
1927TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1929 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001930 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001931 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001932 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001933
1934 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001935 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001936 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001937 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001938
1939 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001940 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001941 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001942 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001943
1944 mDispatcher->setInputWindows(
1945 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
1946
1947 // Touch down on left window
1948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1949 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
1950 {100, 100}))
1951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1952
1953 // Both foreground window and its wallpaper should receive the touch down
1954 leftWindow->consumeMotionDown();
1955 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1956
1957 // Second finger down on the right window
1958 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001959 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001961 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1962 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001963 .build();
1964 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1965 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
1966 InputEventInjectionSync::WAIT_FOR_RESULT))
1967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1968
1969 leftWindow->consumeMotionMove();
1970 // Since the touch is split, right window gets ACTION_DOWN
1971 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001972 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001973 expectedWallpaperFlags);
1974
1975 // Now, leftWindow, which received the first finger, disappears.
1976 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightWindow, wallpaperWindow}}});
1977 leftWindow->consumeMotionCancel();
1978 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1979 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1980
1981 // The pointer that's still down on the right window moves, and goes to the right window only.
1982 // As far as the dispatcher's concerned though, both pointers are still present.
1983 const MotionEvent secondFingerMoveEvent =
1984 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1985 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001986 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1987 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001988 .build();
1989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
1990 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
1991 InputEventInjectionSync::WAIT_FOR_RESULT));
1992 rightWindow->consumeMotionMove();
1993
1994 leftWindow->assertNoEvents();
1995 rightWindow->assertNoEvents();
1996 wallpaperWindow->assertNoEvents();
1997}
1998
Arthur Hungc539dbb2022-12-08 07:45:36 +00001999/**
2000 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2001 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2002 * The right window should receive ACTION_DOWN.
2003 */
2004TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002005 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002006 sp<FakeWindowHandle> leftWindow =
2007 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2008 leftWindow->setFrame(Rect(0, 0, 200, 200));
2009 leftWindow->setDupTouchToWallpaper(true);
2010 leftWindow->setSlippery(true);
2011
2012 sp<FakeWindowHandle> rightWindow =
2013 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2014 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002015
2016 sp<FakeWindowHandle> wallpaperWindow =
2017 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2018 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002019
Arthur Hungc539dbb2022-12-08 07:45:36 +00002020 mDispatcher->setInputWindows(
2021 {{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow, wallpaperWindow}}});
Arthur Hung74c248d2022-11-23 07:09:59 +00002022
Arthur Hungc539dbb2022-12-08 07:45:36 +00002023 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2025 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002026 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002027 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002028
2029 // Both foreground window and its wallpaper should receive the touch down
2030 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002031 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2032
Arthur Hungc539dbb2022-12-08 07:45:36 +00002033 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002035 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
2036 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2038
Arthur Hungc539dbb2022-12-08 07:45:36 +00002039 leftWindow->consumeMotionCancel();
2040 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2041 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002042}
2043
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002044/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002045 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2046 * interactive, it might stop sending this flag.
2047 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2048 * to have a consistent input stream.
2049 *
2050 * Test procedure:
2051 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2052 * DOWN (new gesture).
2053 *
2054 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2055 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2056 *
2057 * We technically just need a single window here, but we are using two windows (spy on top and a
2058 * regular window below) to emulate the actual situation where it happens on the device.
2059 */
2060TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2061 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2062 sp<FakeWindowHandle> spyWindow =
2063 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2064 spyWindow->setFrame(Rect(0, 0, 200, 200));
2065 spyWindow->setTrustedOverlay(true);
2066 spyWindow->setSpy(true);
2067
2068 sp<FakeWindowHandle> window =
2069 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2070 window->setFrame(Rect(0, 0, 200, 200));
2071
2072 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2073 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002074
2075 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002076 mDispatcher->notifyMotion(
2077 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2078 .deviceId(touchDeviceId)
2079 .policyFlags(DEFAULT_POLICY_FLAGS)
2080 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2081 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002082
Prabir Pradhan678438e2023-04-13 19:32:51 +00002083 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2084 .deviceId(touchDeviceId)
2085 .policyFlags(DEFAULT_POLICY_FLAGS)
2086 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2087 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2088 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002089 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2090 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2091 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2092 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2093
2094 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002095 mDispatcher->notifyMotion(
2096 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2097 .deviceId(touchDeviceId)
2098 .policyFlags(0)
2099 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2100 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2101 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002102 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2103 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2104
2105 // We don't need to reset the device to reproduce the issue, but the reset event typically
2106 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002107 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002108
2109 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002110 mDispatcher->notifyMotion(
2111 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2112 .deviceId(touchDeviceId)
2113 .policyFlags(DEFAULT_POLICY_FLAGS)
2114 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2115 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002116 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2117 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2118
2119 // No more events
2120 spyWindow->assertNoEvents();
2121 window->assertNoEvents();
2122}
2123
2124/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002125 * Two windows: a window on the left and a window on the right.
2126 * Mouse is hovered from the right window into the left window.
2127 * Next, we tap on the left window, where the cursor was last seen.
2128 * The second tap is done onto the right window.
2129 * The mouse and tap are from two different devices.
2130 * We technically don't need to set the downtime / eventtime for these events, but setting these
2131 * explicitly helps during debugging.
2132 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2133 * In the buggy implementation, a tap on the right window would cause a crash.
2134 */
2135TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2136 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2137 sp<FakeWindowHandle> leftWindow =
2138 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2139 leftWindow->setFrame(Rect(0, 0, 200, 200));
2140
2141 sp<FakeWindowHandle> rightWindow =
2142 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2143 rightWindow->setFrame(Rect(200, 0, 400, 200));
2144
2145 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2146 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2147 // stale.
2148 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2149 const int32_t mouseDeviceId = 6;
2150 const int32_t touchDeviceId = 4;
2151 // Move the cursor from right
2152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2153 injectMotionEvent(mDispatcher,
2154 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2155 AINPUT_SOURCE_MOUSE)
2156 .deviceId(mouseDeviceId)
2157 .downTime(baseTime + 10)
2158 .eventTime(baseTime + 20)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002159 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002160 .x(300)
2161 .y(100))
2162 .build()));
2163 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2164
2165 // .. to the left window
2166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2167 injectMotionEvent(mDispatcher,
2168 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2169 AINPUT_SOURCE_MOUSE)
2170 .deviceId(mouseDeviceId)
2171 .downTime(baseTime + 10)
2172 .eventTime(baseTime + 30)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002173 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002174 .x(110)
2175 .y(100))
2176 .build()));
2177 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2178 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2179 // Now tap the left window
2180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2181 injectMotionEvent(mDispatcher,
2182 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2183 AINPUT_SOURCE_TOUCHSCREEN)
2184 .deviceId(touchDeviceId)
2185 .downTime(baseTime + 40)
2186 .eventTime(baseTime + 40)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002187 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002188 .x(100)
2189 .y(100))
2190 .build()));
2191 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2192 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2193
2194 // release tap
2195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2196 injectMotionEvent(mDispatcher,
2197 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2198 AINPUT_SOURCE_TOUCHSCREEN)
2199 .deviceId(touchDeviceId)
2200 .downTime(baseTime + 40)
2201 .eventTime(baseTime + 50)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002202 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002203 .x(100)
2204 .y(100))
2205 .build()));
2206 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2207
2208 // Tap the window on the right
2209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2210 injectMotionEvent(mDispatcher,
2211 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2212 AINPUT_SOURCE_TOUCHSCREEN)
2213 .deviceId(touchDeviceId)
2214 .downTime(baseTime + 60)
2215 .eventTime(baseTime + 60)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002216 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002217 .x(300)
2218 .y(100))
2219 .build()));
2220 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2221
2222 // release tap
2223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2224 injectMotionEvent(mDispatcher,
2225 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2226 AINPUT_SOURCE_TOUCHSCREEN)
2227 .deviceId(touchDeviceId)
2228 .downTime(baseTime + 60)
2229 .eventTime(baseTime + 70)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002230 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002231 .x(300)
2232 .y(100))
2233 .build()));
2234 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2235
2236 // No more events
2237 leftWindow->assertNoEvents();
2238 rightWindow->assertNoEvents();
2239}
2240
2241/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002242 * Start hovering in a window. While this hover is still active, make another window appear on top.
2243 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2244 * While the top window is present, the hovering is stopped.
2245 * Later, hovering gets resumed again.
2246 * Ensure that new hover gesture is handled correctly.
2247 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2248 * to the window that's currently being hovered over.
2249 */
2250TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2251 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2252 sp<FakeWindowHandle> window =
2253 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2254 window->setFrame(Rect(0, 0, 200, 200));
2255
2256 // Only a single window is present at first
2257 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2258
2259 // Start hovering in the window
2260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2261 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2262 .build());
2263 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2264
2265 // Now, an obscuring window appears!
2266 sp<FakeWindowHandle> obscuringWindow =
2267 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2268 ADISPLAY_ID_DEFAULT,
2269 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2270 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2271 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2272 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2273 obscuringWindow->setNoInputChannel(true);
2274 obscuringWindow->setFocusable(false);
2275 obscuringWindow->setAlpha(1.0);
2276 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2277
2278 // While this new obscuring window is present, the hovering is stopped
2279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2280 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2281 .build());
2282 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2283
2284 // Now the obscuring window goes away.
2285 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2286
2287 // And a new hover gesture starts.
2288 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2289 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2290 .build());
2291 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2292}
2293
2294/**
2295 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2296 * the obscuring window.
2297 */
2298TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2300 sp<FakeWindowHandle> window =
2301 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2302 window->setFrame(Rect(0, 0, 200, 200));
2303
2304 // Only a single window is present at first
2305 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2306
2307 // Start hovering in the window
2308 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2310 .build());
2311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2312
2313 // Now, an obscuring window appears!
2314 sp<FakeWindowHandle> obscuringWindow =
2315 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2316 ADISPLAY_ID_DEFAULT,
2317 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
2318 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2319 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2320 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2321 obscuringWindow->setNoInputChannel(true);
2322 obscuringWindow->setFocusable(false);
2323 obscuringWindow->setAlpha(1.0);
2324 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
2325
2326 // While this new obscuring window is present, the hovering continues. The event can't go to the
2327 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2329 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2330 .build());
2331 obscuringWindow->assertNoEvents();
2332 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2333
2334 // Now the obscuring window goes away.
2335 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2336
2337 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2338 // so it should generate a HOVER_ENTER
2339 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2340 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2341 .build());
2342 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2343
2344 // Now the MOVE should be getting dispatched normally
2345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2346 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2347 .build());
2348 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2349}
2350
2351/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002352 * Two windows: a window on the left and a window on the right.
2353 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2354 * down. Then, on the left window, also place second touch pointer down.
2355 * This test tries to reproduce a crash.
2356 * In the buggy implementation, second pointer down on the left window would cause a crash.
2357 */
2358TEST_F(InputDispatcherTest, MultiDeviceSplitTouch) {
2359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2360 sp<FakeWindowHandle> leftWindow =
2361 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2362 leftWindow->setFrame(Rect(0, 0, 200, 200));
2363
2364 sp<FakeWindowHandle> rightWindow =
2365 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2366 rightWindow->setFrame(Rect(200, 0, 400, 200));
2367
2368 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2369
2370 const int32_t touchDeviceId = 4;
2371 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002372
2373 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002374 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2375 .deviceId(mouseDeviceId)
2376 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2377 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002378 leftWindow->consumeMotionEvent(
2379 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2380
2381 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002382 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2383 .deviceId(mouseDeviceId)
2384 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2385 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2386 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002387
2388 leftWindow->consumeMotionEvent(
2389 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2390 leftWindow->consumeMotionEvent(
2391 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2392
Prabir Pradhan678438e2023-04-13 19:32:51 +00002393 mDispatcher->notifyMotion(
2394 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2395 .deviceId(mouseDeviceId)
2396 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2397 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2398 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2399 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002400 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2401
2402 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2404 .deviceId(touchDeviceId)
2405 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2406 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002407 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2408
2409 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2410
2411 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002412 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2413 .deviceId(touchDeviceId)
2414 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2415 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2416 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002417 leftWindow->consumeMotionEvent(
2418 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2419 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2420 // current implementation.
2421 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2422 rightWindow->consumeMotionEvent(
2423 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2424
2425 leftWindow->assertNoEvents();
2426 rightWindow->assertNoEvents();
2427}
2428
2429/**
2430 * On a single window, use two different devices: mouse and touch.
2431 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2432 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2433 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2434 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2435 * represent a new gesture.
2436 */
2437TEST_F(InputDispatcherTest, MixedTouchAndMouseWithPointerDown) {
2438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2439 sp<FakeWindowHandle> window =
2440 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2441 window->setFrame(Rect(0, 0, 400, 400));
2442
2443 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2444
2445 const int32_t touchDeviceId = 4;
2446 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002447
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002448 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2450 .deviceId(touchDeviceId)
2451 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2452 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002453 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002454 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2455 .deviceId(touchDeviceId)
2456 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2457 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2458 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002459 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002460 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2461 .deviceId(touchDeviceId)
2462 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2463 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2464 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002465 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2466 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2467 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2468
2469 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2471 .deviceId(mouseDeviceId)
2472 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2473 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2474 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002475
2476 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002477 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002478 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2479
Prabir Pradhan678438e2023-04-13 19:32:51 +00002480 mDispatcher->notifyMotion(
2481 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2482 .deviceId(mouseDeviceId)
2483 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2484 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2485 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2486 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002487 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2488
2489 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002490 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2491 .deviceId(touchDeviceId)
2492 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2493 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2494 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002495 // The pointer_down event should be ignored
2496 window->assertNoEvents();
2497}
2498
2499/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002500 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2501 * the injected event.
2502 */
2503TEST_F(InputDispatcherTest, UnfinishedInjectedEvent) {
2504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2505 sp<FakeWindowHandle> window =
2506 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2507 window->setFrame(Rect(0, 0, 400, 400));
2508
2509 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2510
2511 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002512 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2513 // completion.
2514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2515 injectMotionEvent(mDispatcher,
2516 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2517 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002518 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002519 .x(50)
2520 .y(50))
2521 .build()));
2522 window->consumeMotionEvent(
2523 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2524
2525 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2526 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2528 .deviceId(touchDeviceId)
2529 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2530 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002531
2532 window->consumeMotionEvent(
2533 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2534 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2535}
2536
2537/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002538 * This test is similar to the test above, but the sequence of injected events is different.
2539 *
2540 * Two windows: a window on the left and a window on the right.
2541 * Mouse is hovered over the left window.
2542 * Next, we tap on the left window, where the cursor was last seen.
2543 *
2544 * After that, we inject one finger down onto the right window, and then a second finger down onto
2545 * the left window.
2546 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2547 * window (first), and then another on the left window (second).
2548 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2549 * In the buggy implementation, second finger down on the left window would cause a crash.
2550 */
2551TEST_F(InputDispatcherTest, HoverTapAndSplitTouch) {
2552 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2553 sp<FakeWindowHandle> leftWindow =
2554 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2555 leftWindow->setFrame(Rect(0, 0, 200, 200));
2556
2557 sp<FakeWindowHandle> rightWindow =
2558 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2559 rightWindow->setFrame(Rect(200, 0, 400, 200));
2560
2561 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {leftWindow, rightWindow}}});
2562
2563 const int32_t mouseDeviceId = 6;
2564 const int32_t touchDeviceId = 4;
2565 // Hover over the left window. Keep the cursor there.
2566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2567 injectMotionEvent(mDispatcher,
2568 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2569 AINPUT_SOURCE_MOUSE)
2570 .deviceId(mouseDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002571 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002572 .x(50)
2573 .y(50))
2574 .build()));
2575 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2576
2577 // Tap on left window
2578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2579 injectMotionEvent(mDispatcher,
2580 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2581 AINPUT_SOURCE_TOUCHSCREEN)
2582 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002583 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002584 .x(100)
2585 .y(100))
2586 .build()));
2587
2588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2589 injectMotionEvent(mDispatcher,
2590 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2591 AINPUT_SOURCE_TOUCHSCREEN)
2592 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002593 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002594 .x(100)
2595 .y(100))
2596 .build()));
2597 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2598 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2599 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2600
2601 // First finger down on right window
2602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2603 injectMotionEvent(mDispatcher,
2604 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2605 AINPUT_SOURCE_TOUCHSCREEN)
2606 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002607 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002608 .x(300)
2609 .y(100))
2610 .build()));
2611 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2612
2613 // Second finger down on the left window
2614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2615 injectMotionEvent(mDispatcher,
2616 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2617 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002618 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002619 .x(300)
2620 .y(100))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002621 .pointer(PointerBuilder(1, ToolType::FINGER)
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002622 .x(100)
2623 .y(100))
2624 .build()));
2625 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2626 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2627
2628 // No more events
2629 leftWindow->assertNoEvents();
2630 rightWindow->assertNoEvents();
2631}
2632
2633/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002634 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2635 * While the touch is down, new hover events from the stylus device should be ignored. After the
2636 * touch is gone, stylus hovering should start working again.
2637 */
2638TEST_F(InputDispatcherTest, StylusHoverAndTouchTap) {
2639 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2640 sp<FakeWindowHandle> window =
2641 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2642 window->setFrame(Rect(0, 0, 200, 200));
2643
2644 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
2645
2646 const int32_t stylusDeviceId = 5;
2647 const int32_t touchDeviceId = 4;
2648 // Start hovering with stylus
2649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2650 injectMotionEvent(mDispatcher,
2651 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2652 AINPUT_SOURCE_STYLUS)
2653 .deviceId(stylusDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002654 .pointer(PointerBuilder(0, ToolType::STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002655 .x(50)
2656 .y(50))
2657 .build()));
2658 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2659
2660 // Finger down on the window
2661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2662 injectMotionEvent(mDispatcher,
2663 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2664 AINPUT_SOURCE_TOUCHSCREEN)
2665 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002666 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002667 .x(100)
2668 .y(100))
2669 .build()));
2670 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2671 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2672
2673 // Try to continue hovering with stylus. Since we are already down, injection should fail
2674 ASSERT_EQ(InputEventInjectionResult::FAILED,
2675 injectMotionEvent(mDispatcher,
2676 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2677 AINPUT_SOURCE_STYLUS)
2678 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002679 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002680 .build()));
2681 // No event should be sent. This event should be ignored because a pointer from another device
2682 // is already down.
2683
2684 // Lift up the finger
2685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2686 injectMotionEvent(mDispatcher,
2687 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2688 AINPUT_SOURCE_TOUCHSCREEN)
2689 .deviceId(touchDeviceId)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002690 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002691 .x(100)
2692 .y(100))
2693 .build()));
2694 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2695
2696 // Now that the touch is gone, stylus hovering should start working again
2697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
2698 injectMotionEvent(mDispatcher,
2699 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2700 AINPUT_SOURCE_STYLUS)
2701 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002702 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002703 .build()));
2704 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2705 // No more events
2706 window->assertNoEvents();
2707}
2708
2709/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002710 * A spy window above a window with no input channel.
2711 * Start hovering with a stylus device, and then tap with it.
2712 * Ensure spy window receives the entire sequence.
2713 */
2714TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
2715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2716 sp<FakeWindowHandle> spyWindow =
2717 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2718 spyWindow->setFrame(Rect(0, 0, 200, 200));
2719 spyWindow->setTrustedOverlay(true);
2720 spyWindow->setSpy(true);
2721 sp<FakeWindowHandle> window =
2722 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2723 window->setNoInputChannel(true);
2724 window->setFrame(Rect(0, 0, 200, 200));
2725
2726 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2727
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002728 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00002729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2730 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2731 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002732 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2733 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2735 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2736 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002737 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2738
2739 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002740 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2741 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2742 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002743 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2744
2745 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00002746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2748 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002749 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
2750
2751 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00002752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2753 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2754 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002755 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2756 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00002757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
2759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002760 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2761
2762 // No more events
2763 spyWindow->assertNoEvents();
2764 window->assertNoEvents();
2765}
2766
2767/**
2768 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
2769 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
2770 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
2771 * While the mouse is down, new move events from the touch device should be ignored.
2772 */
2773TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
2774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2775 sp<FakeWindowHandle> spyWindow =
2776 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2777 spyWindow->setFrame(Rect(0, 0, 200, 200));
2778 spyWindow->setTrustedOverlay(true);
2779 spyWindow->setSpy(true);
2780 sp<FakeWindowHandle> window =
2781 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2782 window->setFrame(Rect(0, 0, 200, 200));
2783
2784 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
2785
2786 const int32_t mouseDeviceId = 7;
2787 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002788
2789 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00002790 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2791 .deviceId(mouseDeviceId)
2792 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2793 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002794 spyWindow->consumeMotionEvent(
2795 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2796 window->consumeMotionEvent(
2797 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2798
2799 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00002800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2801 .deviceId(touchDeviceId)
2802 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
2803 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002804 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2805 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2806 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2807 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2808
Prabir Pradhan678438e2023-04-13 19:32:51 +00002809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2810 .deviceId(touchDeviceId)
2811 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
2812 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002813 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2814 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2815
2816 // Pilfer the stream
2817 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
2818 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
2819
Prabir Pradhan678438e2023-04-13 19:32:51 +00002820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2821 .deviceId(touchDeviceId)
2822 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
2823 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002824 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2825
2826 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2828 .deviceId(mouseDeviceId)
2829 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2830 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2831 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002832
2833 spyWindow->consumeMotionEvent(
2834 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2835 spyWindow->consumeMotionEvent(
2836 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2837 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2838
Prabir Pradhan678438e2023-04-13 19:32:51 +00002839 mDispatcher->notifyMotion(
2840 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2841 .deviceId(mouseDeviceId)
2842 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2843 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2844 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2845 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002846 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2847 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2848
2849 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2851 .deviceId(mouseDeviceId)
2852 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2853 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2854 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002855 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2856 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
2857
2858 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00002859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2860 .deviceId(touchDeviceId)
2861 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
2862 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863
2864 // No more events
2865 spyWindow->assertNoEvents();
2866 window->assertNoEvents();
2867}
2868
2869/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002870 * On the display, have a single window, and also an area where there's no window.
2871 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
2872 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
2873 */
2874TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
2875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2876 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002877 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002878
2879 mDispatcher->setInputWindows({{DISPLAY_ID, {window}}});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002880
2881 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00002882 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002883
2884 mDispatcher->waitForIdle();
2885 window->assertNoEvents();
2886
2887 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002888 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002889 mDispatcher->waitForIdle();
2890 window->consumeMotionDown();
2891}
2892
2893/**
2894 * Same test as above, but instead of touching the empty space, the first touch goes to
2895 * non-touchable window.
2896 */
2897TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
2898 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2899 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002900 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002901 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2902 window1->setTouchable(false);
2903 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002904 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002905 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2906
2907 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2908
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002909 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002910 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002911
2912 mDispatcher->waitForIdle();
2913 window1->assertNoEvents();
2914 window2->assertNoEvents();
2915
2916 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002917 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002918 mDispatcher->waitForIdle();
2919 window2->consumeMotionDown();
2920}
2921
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002922/**
2923 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
2924 * to the event time of the first ACTION_DOWN sent to the particular window.
2925 */
2926TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
2927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2928 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002929 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002930 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
2931 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002932 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002933 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
2934
2935 mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
2936
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002937 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002938 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002939
2940 mDispatcher->waitForIdle();
2941 InputEvent* inputEvent1 = window1->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002942 ASSERT_NE(inputEvent1, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002943 window2->assertNoEvents();
2944 MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
2945 nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
2946 ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
2947
2948 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00002949 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002950 mDispatcher->waitForIdle();
2951 InputEvent* inputEvent2 = window2->consume();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002952 ASSERT_NE(inputEvent2, nullptr);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002953 MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
2954 nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
2955 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
2956 ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
2957
2958 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002959 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002960 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002961 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002962
2963 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002964 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002965 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002966 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002967
2968 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
2969 window1->consumeMotionMove();
2970 window1->assertNoEvents();
2971
2972 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002973 mDispatcher->notifyMotion(
2974 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002975 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002976 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002977
Prabir Pradhan678438e2023-04-13 19:32:51 +00002978 mDispatcher->notifyMotion(
2979 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002980 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08002981 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00002982}
2983
Garfield Tandf26e862020-07-01 20:18:19 -07002984TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07002985 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07002986 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002987 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002988 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002989 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002990 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07002991 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07002992
2993 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
2994
2995 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
2996
2997 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08002998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07002999 injectMotionEvent(mDispatcher,
3000 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3001 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003003 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003004 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003005
3006 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003008 injectMotionEvent(mDispatcher,
3009 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3010 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003011 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003012 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003013 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3014 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003015
3016 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003018 injectMotionEvent(mDispatcher,
3019 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3020 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003021 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003022 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003023 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3024 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003025
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003026 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003027 injectMotionEvent(mDispatcher,
3028 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3029 AINPUT_SOURCE_MOUSE)
3030 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3031 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003032 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003033 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003034 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003035
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003036 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003037 injectMotionEvent(mDispatcher,
3038 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3039 AINPUT_SOURCE_MOUSE)
3040 .buttonState(0)
3041 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003042 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003043 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003044 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003045
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003046 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003047 injectMotionEvent(mDispatcher,
3048 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3049 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003050 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003051 .build()));
3052 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3053
3054 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003056 injectMotionEvent(mDispatcher,
3057 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3058 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003059 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003060 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003061 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003062
3063 // No more events
3064 windowLeft->assertNoEvents();
3065 windowRight->assertNoEvents();
3066}
3067
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003068/**
3069 * Put two fingers down (and don't release them) and click the mouse button.
3070 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3071 * currently active gesture should be canceled, and the new one should proceed.
3072 */
3073TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3075 sp<FakeWindowHandle> window =
3076 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3077 window->setFrame(Rect(0, 0, 600, 800));
3078
3079 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3080
3081 const int32_t touchDeviceId = 4;
3082 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003083
3084 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3086 .deviceId(touchDeviceId)
3087 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3088 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003089
Prabir Pradhan678438e2023-04-13 19:32:51 +00003090 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3091 .deviceId(touchDeviceId)
3092 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3093 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3094 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003095 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3096 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3097
3098 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3100 .deviceId(mouseDeviceId)
3101 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3102 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3103 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003104 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3105 WithPointerCount(2u)));
3106 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3107
Prabir Pradhan678438e2023-04-13 19:32:51 +00003108 mDispatcher->notifyMotion(
3109 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3110 .deviceId(mouseDeviceId)
3111 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3112 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3113 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3114 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3116
3117 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3118 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3120 .deviceId(touchDeviceId)
3121 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3122 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3123 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124 window->assertNoEvents();
3125}
3126
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003127TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3128 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3129
3130 sp<FakeWindowHandle> spyWindow =
3131 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3132 spyWindow->setFrame(Rect(0, 0, 600, 800));
3133 spyWindow->setTrustedOverlay(true);
3134 spyWindow->setSpy(true);
3135 sp<FakeWindowHandle> window =
3136 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3137 window->setFrame(Rect(0, 0, 600, 800));
3138
3139 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3140 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3141
3142 // Send mouse cursor to the window
3143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3144 injectMotionEvent(mDispatcher,
3145 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3146 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003147 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003148 .x(100)
3149 .y(100))
3150 .build()));
3151
3152 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3153 WithSource(AINPUT_SOURCE_MOUSE)));
3154 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3155 WithSource(AINPUT_SOURCE_MOUSE)));
3156
3157 window->assertNoEvents();
3158 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003159}
3160
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003161TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3162 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3163
3164 sp<FakeWindowHandle> spyWindow =
3165 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3166 spyWindow->setFrame(Rect(0, 0, 600, 800));
3167 spyWindow->setTrustedOverlay(true);
3168 spyWindow->setSpy(true);
3169 sp<FakeWindowHandle> window =
3170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3171 window->setFrame(Rect(0, 0, 600, 800));
3172
3173 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3174 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
3175
3176 // Send mouse cursor to the window
3177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3178 injectMotionEvent(mDispatcher,
3179 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3180 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003181 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003182 .x(100)
3183 .y(100))
3184 .build()));
3185
3186 // Move mouse cursor
3187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3188 injectMotionEvent(mDispatcher,
3189 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3190 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003191 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003192 .x(110)
3193 .y(110))
3194 .build()));
3195
3196 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3197 WithSource(AINPUT_SOURCE_MOUSE)));
3198 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3199 WithSource(AINPUT_SOURCE_MOUSE)));
3200 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3201 WithSource(AINPUT_SOURCE_MOUSE)));
3202 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3203 WithSource(AINPUT_SOURCE_MOUSE)));
3204 // Touch down on the window
3205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3206 injectMotionEvent(mDispatcher,
3207 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3208 AINPUT_SOURCE_TOUCHSCREEN)
3209 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003210 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003211 .x(200)
3212 .y(200))
3213 .build()));
3214 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3215 WithSource(AINPUT_SOURCE_MOUSE)));
3216 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3217 WithSource(AINPUT_SOURCE_MOUSE)));
3218 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3219 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3220 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3221 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3222
3223 // pilfer the motion, retaining the gesture on the spy window.
3224 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3225 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3226 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3227
3228 // Touch UP on the window
3229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3230 injectMotionEvent(mDispatcher,
3231 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
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 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3239 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3240
3241 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3242 // to send a new gesture. It should again go to both windows (spy and the window below), just
3243 // like the first gesture did, before pilfering. The window configuration has not changed.
3244
3245 // One more tap - DOWN
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3247 injectMotionEvent(mDispatcher,
3248 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3249 AINPUT_SOURCE_TOUCHSCREEN)
3250 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003251 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003252 .x(250)
3253 .y(250))
3254 .build()));
3255 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3256 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3257 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3258 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3259
3260 // Touch UP on the window
3261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3262 injectMotionEvent(mDispatcher,
3263 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3264 AINPUT_SOURCE_TOUCHSCREEN)
3265 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003266 .pointer(PointerBuilder(0, ToolType::FINGER)
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003267 .x(250)
3268 .y(250))
3269 .build()));
3270 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3271 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3272 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3273 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3274
3275 window->assertNoEvents();
3276 spyWindow->assertNoEvents();
3277}
3278
Garfield Tandf26e862020-07-01 20:18:19 -07003279// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3280// directly in this test.
3281TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003283 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003284 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003285 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003286
3287 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3288
3289 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3290
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003292 injectMotionEvent(mDispatcher,
3293 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3294 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003295 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003296 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003297 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003298 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003300 injectMotionEvent(mDispatcher,
3301 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3302 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003303 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003304 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003305 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3306 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003307
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003309 injectMotionEvent(mDispatcher,
3310 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3311 AINPUT_SOURCE_MOUSE)
3312 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3313 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003314 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003315 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003316 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003317
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003319 injectMotionEvent(mDispatcher,
3320 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3321 AINPUT_SOURCE_MOUSE)
3322 .buttonState(0)
3323 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003324 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003325 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003326 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003327
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tandf26e862020-07-01 20:18:19 -07003329 injectMotionEvent(mDispatcher,
3330 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3331 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003332 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003333 .build()));
3334 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3335
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003336 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3337 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3338 ASSERT_EQ(InputEventInjectionResult::FAILED,
Garfield Tandf26e862020-07-01 20:18:19 -07003339 injectMotionEvent(mDispatcher,
3340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3341 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003342 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003343 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003344 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003345}
3346
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003347/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003348 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3349 * is generated.
3350 */
3351TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3353 sp<FakeWindowHandle> window =
3354 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3355 window->setFrame(Rect(0, 0, 1200, 800));
3356
3357 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3358
3359 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3360
3361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3362 injectMotionEvent(mDispatcher,
3363 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3364 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003365 .pointer(PointerBuilder(0, ToolType::MOUSE)
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003366 .x(300)
3367 .y(400))
3368 .build()));
3369 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3370
3371 // Remove the window, but keep the channel.
3372 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
3373 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3374}
3375
3376/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003377 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3378 */
3379TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3381 sp<FakeWindowHandle> window =
3382 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3383 window->setFrame(Rect(0, 0, 100, 100));
3384
3385 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3386
3387 const int32_t mouseDeviceId = 7;
3388 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003389
3390 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3392 .deviceId(mouseDeviceId)
3393 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3394 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003395 window->consumeMotionEvent(
3396 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3397
3398 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3400 .deviceId(touchDeviceId)
3401 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3402 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003403
3404 window->consumeMotionEvent(
3405 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3407}
3408
3409/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003410 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003411 * The tap causes a HOVER_EXIT event to be generated because the current event
3412 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003413 */
3414TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3416 sp<FakeWindowHandle> window =
3417 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3418 window->setFrame(Rect(0, 0, 100, 100));
3419
3420 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3421
3422 // Inject a hover_move from mouse.
3423 NotifyMotionArgs motionArgs =
3424 generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE,
3425 ADISPLAY_ID_DEFAULT, {{50, 50}});
3426 motionArgs.xCursorPosition = 50;
3427 motionArgs.yCursorPosition = 50;
Prabir Pradhan678438e2023-04-13 19:32:51 +00003428 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003429 ASSERT_NO_FATAL_FAILURE(
3430 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3431 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003432
3433 // Tap on the window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003434 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3435 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3436 {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003437 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003438 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3439 WithSource(AINPUT_SOURCE_MOUSE))));
3440
3441 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003442 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3443 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3444
Prabir Pradhan678438e2023-04-13 19:32:51 +00003445 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
3446 ADISPLAY_ID_DEFAULT, {{10, 10}}));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003447 ASSERT_NO_FATAL_FAILURE(
3448 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3449 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3450}
3451
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003452TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3454 sp<FakeWindowHandle> windowDefaultDisplay =
3455 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3456 ADISPLAY_ID_DEFAULT);
3457 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3458 sp<FakeWindowHandle> windowSecondDisplay =
3459 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3460 SECOND_DISPLAY_ID);
3461 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3462
3463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3464 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3465
3466 // Set cursor position in window in default display and check that hover enter and move
3467 // events are generated.
3468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3469 injectMotionEvent(mDispatcher,
3470 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3471 AINPUT_SOURCE_MOUSE)
3472 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003473 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003474 .x(300)
3475 .y(600))
3476 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003477 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003478
3479 // Remove all windows in secondary display and check that no event happens on window in
3480 // primary display.
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003481 mDispatcher->setInputWindows(
3482 {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003483 windowDefaultDisplay->assertNoEvents();
3484
3485 // Move cursor position in window in default display and check that only hover move
3486 // event is generated and not hover enter event.
3487 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}},
3488 {SECOND_DISPLAY_ID, {windowSecondDisplay}}});
3489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3490 injectMotionEvent(mDispatcher,
3491 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3492 AINPUT_SOURCE_MOUSE)
3493 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003494 .pointer(PointerBuilder(0, ToolType::MOUSE)
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003495 .x(400)
3496 .y(700))
3497 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003498 windowDefaultDisplay->consumeMotionEvent(
3499 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3500 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003501 windowDefaultDisplay->assertNoEvents();
3502}
3503
Garfield Tan00f511d2019-06-12 16:55:40 -07003504TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003505 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003506
3507 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003508 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003509 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003510 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003511 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003512 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003513
3514 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3515
Arthur Hung72d8dc32020-03-28 00:48:39 +00003516 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowLeft, windowRight}}});
Garfield Tan00f511d2019-06-12 16:55:40 -07003517
3518 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3519 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003520 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Garfield Tan00f511d2019-06-12 16:55:40 -07003521 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003522 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003523 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003524 windowRight->assertNoEvents();
3525}
3526
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003527TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003528 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003529 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3530 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003531 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003532
Arthur Hung72d8dc32020-03-28 00:48:39 +00003533 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07003534 setFocusedWindow(window);
3535
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003536 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003537
Prabir Pradhan678438e2023-04-13 19:32:51 +00003538 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003539
3540 // Window should receive key down event.
3541 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3542
3543 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3544 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003545 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07003546 window->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003547 AKEY_EVENT_FLAG_CANCELED);
3548}
3549
3550TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003551 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003552 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3553 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003554
Arthur Hung72d8dc32020-03-28 00:48:39 +00003555 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003556
Prabir Pradhan678438e2023-04-13 19:32:51 +00003557 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3558 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003559
3560 // Window should receive motion down event.
3561 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3562
3563 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
3564 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003565 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08003566 window->consumeMotionEvent(
3567 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003568}
3569
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07003570TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
3571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3572 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3573 "Fake Window", ADISPLAY_ID_DEFAULT);
3574
3575 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3576
3577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3578 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
3579 .build());
3580
3581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3582
3583 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
3584 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
3585 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3586
3587 // After the device has been reset, a new hovering stream can be sent to the window
3588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3589 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
3590 .build());
3591 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3592}
3593
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003594TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003596 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3597 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003598 window->setFocusable(true);
3599
3600 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3601 setFocusedWindow(window);
3602
3603 window->consumeFocusEvent(true);
3604
Prabir Pradhan678438e2023-04-13 19:32:51 +00003605 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003606 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
3607 const nsecs_t injectTime = keyArgs.eventTime;
3608 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00003609 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003610 // The dispatching time should be always greater than or equal to intercept key timeout.
3611 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3612 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
3613 std::chrono::nanoseconds(interceptKeyTimeout).count());
3614}
3615
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003616/**
3617 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
3618 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003619TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
3620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003621 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3622 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003623 window->setFocusable(true);
3624
3625 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3626 setFocusedWindow(window);
3627
3628 window->consumeFocusEvent(true);
3629
Prabir Pradhan678438e2023-04-13 19:32:51 +00003630 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003631 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07003632
3633 // Set a value that's significantly larger than the default consumption timeout. If the
3634 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
3635 mFakePolicy->setInterceptKeyTimeout(600ms);
3636 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
3637 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08003638 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3639}
3640
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07003641/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003642 * Two windows. First is a regular window. Second does not overlap with the first, and has
3643 * WATCH_OUTSIDE_TOUCH.
3644 * Both windows are owned by the same UID.
3645 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
3646 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
3647 */
3648TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
3649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3650 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3651 "First Window", ADISPLAY_ID_DEFAULT);
3652 window->setFrame(Rect{0, 0, 100, 100});
3653
3654 sp<FakeWindowHandle> outsideWindow =
3655 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3656 ADISPLAY_ID_DEFAULT);
3657 outsideWindow->setFrame(Rect{100, 100, 200, 200});
3658 outsideWindow->setWatchOutsideTouch(true);
3659 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
3660 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {outsideWindow, window}}});
3661
3662 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003663 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3664 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3665 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003666 window->consumeMotionDown();
3667 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
3668 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
3669 outsideWindow->consumeMotionEvent(
3670 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
3671}
3672
3673/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003674 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
3675 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
3676 * ACTION_OUTSIDE event is sent per gesture.
3677 */
3678TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
3679 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
3680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3682 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003683 window->setWatchOutsideTouch(true);
3684 window->setFrame(Rect{0, 0, 100, 100});
3685 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003686 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
3687 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003688 secondWindow->setFrame(Rect{100, 100, 200, 200});
3689 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003690 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
3691 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003692 thirdWindow->setFrame(Rect{200, 200, 300, 300});
3693 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});
3694
3695 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003696 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3697 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3698 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003699 window->assertNoEvents();
3700 secondWindow->assertNoEvents();
3701
3702 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
3703 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003704 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
3705 ADISPLAY_ID_DEFAULT,
3706 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08003707 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
3708 window->consumeMotionEvent(
3709 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003710 secondWindow->consumeMotionDown();
3711 thirdWindow->assertNoEvents();
3712
3713 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
3714 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003715 mDispatcher->notifyMotion(
3716 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3717 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003718 window->assertNoEvents();
3719 secondWindow->consumeMotionMove();
3720 thirdWindow->consumeMotionDown();
3721}
3722
Prabir Pradhan814fe082022-07-22 20:22:18 +00003723TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
3724 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003725 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3726 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003727 window->setFocusable(true);
3728
Patrick Williamsd828f302023-04-28 17:52:08 -05003729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003730 setFocusedWindow(window);
3731
3732 window->consumeFocusEvent(true);
3733
Prabir Pradhan678438e2023-04-13 19:32:51 +00003734 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
3735 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
3736 mDispatcher->notifyKey(keyDown);
3737 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003738
3739 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3740 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
3741
3742 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05003743 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00003744
3745 window->consumeFocusEvent(false);
3746
Prabir Pradhan678438e2023-04-13 19:32:51 +00003747 mDispatcher->notifyKey(keyDown);
3748 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00003749 window->assertNoEvents();
3750}
3751
Arthur Hung96483742022-11-15 03:30:48 +00003752TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
3753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3755 "Fake Window", ADISPLAY_ID_DEFAULT);
3756 // Ensure window is non-split and have some transform.
3757 window->setPreventSplitting(true);
3758 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05003759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00003760
3761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3762 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
3763 {50, 50}))
3764 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3765 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
3766
3767 const MotionEvent secondFingerDownEvent =
3768 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3769 .displayId(ADISPLAY_ID_DEFAULT)
3770 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003771 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3772 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00003773 .build();
3774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3775 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
3776 InputEventInjectionSync::WAIT_FOR_RESULT))
3777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
3778
3779 const MotionEvent* event = window->consumeMotion();
3780 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
3781 EXPECT_EQ(70, event->getX(0)); // 50 + 20
3782 EXPECT_EQ(90, event->getY(0)); // 50 + 40
3783 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
3784 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
3785}
3786
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003787/**
3788 * Two windows: a splittable and a non-splittable.
3789 * The non-splittable window shouldn't receive any "incomplete" gestures.
3790 * Send the first pointer to the splittable window, and then touch the non-splittable window.
3791 * The second pointer should be dropped because the initial window is splittable, so it won't get
3792 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
3793 * "incomplete" gestures.
3794 */
3795TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
3796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3797 sp<FakeWindowHandle> leftWindow =
3798 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
3799 ADISPLAY_ID_DEFAULT);
3800 leftWindow->setPreventSplitting(false);
3801 leftWindow->setFrame(Rect(0, 0, 100, 100));
3802 sp<FakeWindowHandle> rightWindow =
3803 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
3804 ADISPLAY_ID_DEFAULT);
3805 rightWindow->setPreventSplitting(true);
3806 rightWindow->setFrame(Rect(100, 100, 200, 200));
3807 mDispatcher->onWindowInfosChanged(
3808 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3809
3810 // Touch down on left, splittable window
3811 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3812 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3813 .build());
3814 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3815
3816 mDispatcher->notifyMotion(
3817 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3818 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
3819 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
3820 .build());
3821 leftWindow->assertNoEvents();
3822 rightWindow->assertNoEvents();
3823}
3824
Harry Cuttsb166c002023-05-09 13:06:05 +00003825TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
3826 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3827 sp<FakeWindowHandle> window =
3828 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3829 window->setFrame(Rect(0, 0, 400, 400));
3830 sp<FakeWindowHandle> trustedOverlay =
3831 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
3832 ADISPLAY_ID_DEFAULT);
3833 trustedOverlay->setSpy(true);
3834 trustedOverlay->setTrustedOverlay(true);
3835
3836 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});
3837
3838 // Start a three-finger touchpad swipe
3839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3841 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3842 .build());
3843 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3844 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3845 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3846 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3847 .build());
3848 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3849 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3850 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3851 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3852 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3853 .build());
3854
3855 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3856 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3857 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
3858
3859 // Move the swipe a bit
3860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3861 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3862 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3863 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3864 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3865 .build());
3866
3867 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3868
3869 // End the swipe
3870 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3872 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3873 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3874 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3875 .build());
3876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3877 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3878 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3879 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3880 .build());
3881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3882 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3883 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3884 .build());
3885
3886 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
3887 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3888 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
3889
3890 window->assertNoEvents();
3891}
3892
3893TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
3894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3895 sp<FakeWindowHandle> window =
3896 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3897 window->setFrame(Rect(0, 0, 400, 400));
3898 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
3899
3900 // Start a three-finger touchpad swipe
3901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3902 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3903 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3904 .build());
3905 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3907 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3908 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3909 .build());
3910 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
3911 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
3912 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
3913 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
3914 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3915 .build());
3916
3917 // Move the swipe a bit
3918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3919 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3920 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3921 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3922 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3923 .build());
3924
3925 // End the swipe
3926 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
3927 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3928 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3929 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
3930 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3931 .build());
3932 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
3933 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3934 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
3935 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3936 .build());
3937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
3938 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
3939 .classification(MotionClassification::MULTI_FINGER_SWIPE)
3940 .build());
3941
3942 window->assertNoEvents();
3943}
3944
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00003945/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003946 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
3947 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003948 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003949 */
3950TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
3951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3952 sp<FakeWindowHandle> window =
3953 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3954 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003955 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003956
3957 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
3958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3959 .downTime(baseTime + 10)
3960 .eventTime(baseTime + 10)
3961 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3962 .build());
3963
3964 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3965
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003966 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003967 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003968
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07003969 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003970
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003971 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3972 .downTime(baseTime + 10)
3973 .eventTime(baseTime + 30)
3974 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3975 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3976 .build());
3977
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003978 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3979
3980 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003981 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
3982 .downTime(baseTime + 10)
3983 .eventTime(baseTime + 40)
3984 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3985 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
3986 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003987
3988 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
3989
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3991 .downTime(baseTime + 10)
3992 .eventTime(baseTime + 50)
3993 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3994 .build());
3995
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00003996 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
3997
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07003998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3999 .downTime(baseTime + 60)
4000 .eventTime(baseTime + 60)
4001 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4002 .build());
4003
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004004 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004005}
4006
4007/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004008 * Ensure the correct coordinate spaces are used by InputDispatcher.
4009 *
4010 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4011 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4012 * space.
4013 */
4014class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4015public:
4016 void SetUp() override {
4017 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004018 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004019 }
4020
4021 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4022 gui::DisplayInfo info;
4023 info.displayId = displayId;
4024 info.transform = transform;
4025 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004026 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004027 }
4028
4029 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4030 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004031 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004032 }
4033
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004034 void removeAllWindowsAndDisplays() {
4035 mDisplayInfos.clear();
4036 mWindowInfos.clear();
4037 }
4038
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004039 // Set up a test scenario where the display has a scaled projection and there are two windows
4040 // on the display.
4041 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4042 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4043 // respectively.
4044 ui::Transform displayTransform;
4045 displayTransform.set(2, 0, 0, 4);
4046 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4047
4048 std::shared_ptr<FakeApplicationHandle> application =
4049 std::make_shared<FakeApplicationHandle>();
4050
4051 // Add two windows to the display. Their frames are represented in the display space.
4052 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004053 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4054 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004055 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4056 addWindow(firstWindow);
4057
4058 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004059 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4060 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004061 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4062 addWindow(secondWindow);
4063 return {std::move(firstWindow), std::move(secondWindow)};
4064 }
4065
4066private:
4067 std::vector<gui::DisplayInfo> mDisplayInfos;
4068 std::vector<gui::WindowInfo> mWindowInfos;
4069};
4070
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004071TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004072 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4073 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004074 // selected so that if the hit test was performed with the point and the bounds being in
4075 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004076 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4077 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4078 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004079
4080 firstWindow->consumeMotionDown();
4081 secondWindow->assertNoEvents();
4082}
4083
4084// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4085// the event should be treated as being in the logical display space.
4086TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4087 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4088 // Send down to the first window. The point is represented in the logical display space. The
4089 // point is selected so that if the hit test was done in logical display space, then it would
4090 // end up in the incorrect window.
4091 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4092 PointF{75 * 2, 55 * 4});
4093
4094 firstWindow->consumeMotionDown();
4095 secondWindow->assertNoEvents();
4096}
4097
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004098// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4099// event should be treated as being in the logical display space.
4100TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4101 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4102
4103 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4104 ui::Transform injectedEventTransform;
4105 injectedEventTransform.set(matrix);
4106 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4107 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4108
4109 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4110 .displayId(ADISPLAY_ID_DEFAULT)
4111 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004112 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004113 .x(untransformedPoint.x)
4114 .y(untransformedPoint.y))
4115 .build();
4116 event.transform(matrix);
4117
4118 injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
4119 InputEventInjectionSync::WAIT_FOR_RESULT);
4120
4121 firstWindow->consumeMotionDown();
4122 secondWindow->assertNoEvents();
4123}
4124
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004125TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4126 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4127
4128 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004129 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4130 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4131 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004132
4133 firstWindow->assertNoEvents();
4134 const MotionEvent* event = secondWindow->consumeMotion();
Siarhei Vishniakoub681c202023-05-01 11:22:33 -07004135 ASSERT_NE(nullptr, event);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004136 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
4137
4138 // Ensure that the events from the "getRaw" API are in logical display coordinates.
4139 EXPECT_EQ(300, event->getRawX(0));
4140 EXPECT_EQ(880, event->getRawY(0));
4141
4142 // Ensure that the x and y values are in the window's coordinate space.
4143 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4144 // the logical display space. This will be the origin of the window space.
4145 EXPECT_EQ(100, event->getX(0));
4146 EXPECT_EQ(80, event->getY(0));
4147}
4148
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004149/** Ensure consistent behavior of InputDispatcher in all orientations. */
4150class InputDispatcherDisplayOrientationFixture
4151 : public InputDispatcherDisplayProjectionTest,
4152 public ::testing::WithParamInterface<ui::Rotation> {};
4153
4154// This test verifies the touchable region of a window for all rotations of the display by tapping
4155// in different locations on the display, specifically points close to the four corners of a
4156// window.
4157TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4158 constexpr static int32_t displayWidth = 400;
4159 constexpr static int32_t displayHeight = 800;
4160
4161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4162
4163 const auto rotation = GetParam();
4164
4165 // Set up the display with the specified rotation.
4166 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4167 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4168 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4169 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4170 logicalDisplayWidth, logicalDisplayHeight);
4171 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4172
4173 // Create a window with its bounds determined in the logical display.
4174 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4175 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4176 sp<FakeWindowHandle> window =
4177 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4178 window->setFrame(frameInDisplay, displayTransform);
4179 addWindow(window);
4180
4181 // The following points in logical display space should be inside the window.
4182 static const std::array<vec2, 4> insidePoints{
4183 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4184 for (const auto pointInsideWindow : insidePoints) {
4185 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4186 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004187 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4188 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4189 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004190 window->consumeMotionDown();
4191
Prabir Pradhan678438e2023-04-13 19:32:51 +00004192 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4193 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4194 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004195 window->consumeMotionUp();
4196 }
4197
4198 // The following points in logical display space should be outside the window.
4199 static const std::array<vec2, 5> outsidePoints{
4200 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4201 for (const auto pointOutsideWindow : outsidePoints) {
4202 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4203 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004204 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4205 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4206 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004207
Prabir Pradhan678438e2023-04-13 19:32:51 +00004208 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4209 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4210 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004211 }
4212 window->assertNoEvents();
4213}
4214
4215// Run the precision tests for all rotations.
4216INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4217 InputDispatcherDisplayOrientationFixture,
4218 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4219 ui::ROTATION_270),
4220 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4221 return ftl::enum_string(testParamInfo.param);
4222 });
4223
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004224using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4225 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004226
4227class TransferTouchFixture : public InputDispatcherTest,
4228 public ::testing::WithParamInterface<TransferFunction> {};
4229
4230TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004231 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004232
4233 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004234 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004235 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4236 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004237 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004238 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004239 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4240 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004241 sp<FakeWindowHandle> wallpaper =
4242 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4243 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004244 // Add the windows to the dispatcher
Arthur Hungc539dbb2022-12-08 07:45:36 +00004245 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow, wallpaper}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004246
4247 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004248 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4249 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004250
Svet Ganov5d3bc372020-01-26 23:11:07 -08004251 // Only the first window should get the down event
4252 firstWindow->consumeMotionDown();
4253 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004254 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004255
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004256 // Transfer touch to the second window
4257 TransferFunction f = GetParam();
4258 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4259 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004260 // The first window gets cancel and the second gets down
4261 firstWindow->consumeMotionCancel();
4262 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004263 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004264
4265 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004266 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4267 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004268 // The first window gets no events and the second gets up
4269 firstWindow->assertNoEvents();
4270 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004271 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004272}
4273
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004274/**
4275 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
4276 * from. When we have spy windows, there are several windows to choose from: either spy, or the
4277 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
4278 * natural to the user.
4279 * In this test, we are sending a pointer to both spy window and first window. We then try to
4280 * transfer touch to the second window. The dispatcher should identify the first window as the
4281 * one that should lose the gesture, and therefore the action should be to move the gesture from
4282 * the first window to the second.
4283 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
4284 * the other API, as well.
4285 */
4286TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
4287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4288
4289 // Create a couple of windows + a spy window
4290 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004291 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004292 spyWindow->setTrustedOverlay(true);
4293 spyWindow->setSpy(true);
4294 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004295 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004296 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004297 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004298
4299 // Add the windows to the dispatcher
4300 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, firstWindow, secondWindow}}});
4301
4302 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004303 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4304 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004305 // Only the first window and spy should get the down event
4306 spyWindow->consumeMotionDown();
4307 firstWindow->consumeMotionDown();
4308
4309 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
4310 // if f === 'transferTouch'.
4311 TransferFunction f = GetParam();
4312 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4313 ASSERT_TRUE(success);
4314 // The first window gets cancel and the second gets down
4315 firstWindow->consumeMotionCancel();
4316 secondWindow->consumeMotionDown();
4317
4318 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004319 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4320 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004321 // The first window gets no events and the second+spy get up
4322 firstWindow->assertNoEvents();
4323 spyWindow->consumeMotionUp();
4324 secondWindow->consumeMotionUp();
4325}
4326
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004327TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004329
4330 PointF touchPoint = {10, 10};
4331
4332 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004333 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004334 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4335 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004336 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004337 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004338 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4339 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08004340 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004341
4342 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004343 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004344
4345 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004346 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4347 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4348 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004349 // Only the first window should get the down event
4350 firstWindow->consumeMotionDown();
4351 secondWindow->assertNoEvents();
4352
4353 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004354 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4355 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004356 // Only the first window should get the pointer down event
4357 firstWindow->consumeMotionPointerDown(1);
4358 secondWindow->assertNoEvents();
4359
4360 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004361 TransferFunction f = GetParam();
4362 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4363 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004364 // The first window gets cancel and the second gets down and pointer down
4365 firstWindow->consumeMotionCancel();
4366 secondWindow->consumeMotionDown();
4367 secondWindow->consumeMotionPointerDown(1);
4368
4369 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004370 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4371 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004372 // The first window gets nothing and the second gets pointer up
4373 firstWindow->assertNoEvents();
4374 secondWindow->consumeMotionPointerUp(1);
4375
4376 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004377 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4378 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004379 // The first window gets nothing and the second gets up
4380 firstWindow->assertNoEvents();
4381 secondWindow->consumeMotionUp();
4382}
4383
Arthur Hungc539dbb2022-12-08 07:45:36 +00004384TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
4385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4386
4387 // Create a couple of windows
4388 sp<FakeWindowHandle> firstWindow =
4389 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4390 ADISPLAY_ID_DEFAULT);
4391 firstWindow->setDupTouchToWallpaper(true);
4392 sp<FakeWindowHandle> secondWindow =
4393 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4394 ADISPLAY_ID_DEFAULT);
4395 secondWindow->setDupTouchToWallpaper(true);
4396
4397 sp<FakeWindowHandle> wallpaper1 =
4398 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
4399 wallpaper1->setIsWallpaper(true);
4400
4401 sp<FakeWindowHandle> wallpaper2 =
4402 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
4403 wallpaper2->setIsWallpaper(true);
4404 // Add the windows to the dispatcher
4405 mDispatcher->setInputWindows(
4406 {{ADISPLAY_ID_DEFAULT, {firstWindow, wallpaper1, secondWindow, wallpaper2}}});
4407
4408 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004409 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4410 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004411
4412 // Only the first window should get the down event
4413 firstWindow->consumeMotionDown();
4414 secondWindow->assertNoEvents();
4415 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4416 wallpaper2->assertNoEvents();
4417
4418 // Transfer touch focus to the second window
4419 TransferFunction f = GetParam();
4420 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4421 ASSERT_TRUE(success);
4422
4423 // The first window gets cancel and the second gets down
4424 firstWindow->consumeMotionCancel();
4425 secondWindow->consumeMotionDown();
4426 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4427 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4428
4429 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004430 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4431 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004432 // The first window gets no events and the second gets up
4433 firstWindow->assertNoEvents();
4434 secondWindow->consumeMotionUp();
4435 wallpaper1->assertNoEvents();
4436 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
4437}
4438
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004439// For the cases of single pointer touch and two pointers non-split touch, the api's
4440// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
4441// for the case where there are multiple pointers split across several windows.
4442INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
4443 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004444 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4445 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004446 return dispatcher->transferTouch(destChannelToken,
4447 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004448 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004449 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
4450 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004451 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00004452 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004453 }));
4454
Svet Ganov5d3bc372020-01-26 23:11:07 -08004455TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07004456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004457
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004458 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004459 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4460 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004461 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004462
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004463 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004464 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4465 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004466 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004467
4468 // Add the windows to the dispatcher
Arthur Hung72d8dc32020-03-28 00:48:39 +00004469 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
Svet Ganov5d3bc372020-01-26 23:11:07 -08004470
4471 PointF pointInFirst = {300, 200};
4472 PointF pointInSecond = {300, 600};
4473
4474 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004475 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4476 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4477 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004478 // Only the first window should get the down event
4479 firstWindow->consumeMotionDown();
4480 secondWindow->assertNoEvents();
4481
4482 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004483 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4484 ADISPLAY_ID_DEFAULT,
4485 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004486 // The first window gets a move and the second a down
4487 firstWindow->consumeMotionMove();
4488 secondWindow->consumeMotionDown();
4489
4490 // Transfer touch focus to the second window
4491 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
4492 // The first window gets cancel and the new gets pointer down (it already saw down)
4493 firstWindow->consumeMotionCancel();
4494 secondWindow->consumeMotionPointerDown(1);
4495
4496 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004497 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4498 ADISPLAY_ID_DEFAULT,
4499 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004500 // The first window gets nothing and the second gets pointer up
4501 firstWindow->assertNoEvents();
4502 secondWindow->consumeMotionPointerUp(1);
4503
4504 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4506 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08004507 // The first window gets nothing and the second gets up
4508 firstWindow->assertNoEvents();
4509 secondWindow->consumeMotionUp();
4510}
4511
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004512// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
4513// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
4514// touch is not supported, so the touch should continue on those windows and the transferred-to
4515// window should get nothing.
4516TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
4517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4518
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004519 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004520 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4521 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004522 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004523
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004524 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004525 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4526 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004527 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004528
4529 // Add the windows to the dispatcher
4530 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4531
4532 PointF pointInFirst = {300, 200};
4533 PointF pointInSecond = {300, 600};
4534
4535 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004536 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4537 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4538 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004539 // Only the first window should get the down event
4540 firstWindow->consumeMotionDown();
4541 secondWindow->assertNoEvents();
4542
4543 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004544 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4545 ADISPLAY_ID_DEFAULT,
4546 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004547 // The first window gets a move and the second a down
4548 firstWindow->consumeMotionMove();
4549 secondWindow->consumeMotionDown();
4550
4551 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004552 const bool transferred =
4553 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004554 // The 'transferTouch' call should not succeed, because there are 2 touched windows
4555 ASSERT_FALSE(transferred);
4556 firstWindow->assertNoEvents();
4557 secondWindow->assertNoEvents();
4558
4559 // The rest of the dispatch should proceed as normal
4560 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004561 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
4562 ADISPLAY_ID_DEFAULT,
4563 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004564 // The first window gets MOVE and the second gets pointer up
4565 firstWindow->consumeMotionMove();
4566 secondWindow->consumeMotionUp();
4567
4568 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4570 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004571 // The first window gets nothing and the second gets up
4572 firstWindow->consumeMotionUp();
4573 secondWindow->assertNoEvents();
4574}
4575
Arthur Hungabbb9d82021-09-01 14:52:30 +00004576// This case will create two windows and one mirrored window on the default display and mirror
4577// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
4578// the windows info of second display before default display.
4579TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
4580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4581 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004582 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004583 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004584 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004585 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004586 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004587
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004588 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004589 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004590
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004591 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004592 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004593
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004594 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004595 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004596
4597 // Update window info, let it find window handle of second display first.
4598 mDispatcher->setInputWindows(
4599 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4600 {ADISPLAY_ID_DEFAULT,
4601 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4602
4603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4604 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4605 {50, 50}))
4606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4607
4608 // Window should receive motion event.
4609 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4610
4611 // Transfer touch focus
4612 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
4613 secondWindowInPrimary->getToken()));
4614 // The first window gets cancel.
4615 firstWindowInPrimary->consumeMotionCancel();
4616 secondWindowInPrimary->consumeMotionDown();
4617
4618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4619 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4620 ADISPLAY_ID_DEFAULT, {150, 50}))
4621 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4622 firstWindowInPrimary->assertNoEvents();
4623 secondWindowInPrimary->consumeMotionMove();
4624
4625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4626 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4627 {150, 50}))
4628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4629 firstWindowInPrimary->assertNoEvents();
4630 secondWindowInPrimary->consumeMotionUp();
4631}
4632
4633// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
4634// 'transferTouch' api.
4635TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
4636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4637 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004638 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004639 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004640 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004641 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004642 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004643
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004644 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004645 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004646
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004647 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004648 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004649
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004650 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00004651 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004652
4653 // Update window info, let it find window handle of second display first.
4654 mDispatcher->setInputWindows(
4655 {{SECOND_DISPLAY_ID, {firstWindowInSecondary, secondWindowInSecondary}},
4656 {ADISPLAY_ID_DEFAULT,
4657 {mirrorWindowInPrimary, firstWindowInPrimary, secondWindowInPrimary}}});
4658
4659 // Touch on second display.
4660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4661 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {50, 50}))
4662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4663
4664 // Window should receive motion event.
4665 firstWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4666
4667 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07004668 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00004669
4670 // The first window gets cancel.
4671 firstWindowInPrimary->consumeMotionCancel(SECOND_DISPLAY_ID);
4672 secondWindowInPrimary->consumeMotionDown(SECOND_DISPLAY_ID);
4673
4674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4675 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4676 SECOND_DISPLAY_ID, {150, 50}))
4677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4678 firstWindowInPrimary->assertNoEvents();
4679 secondWindowInPrimary->consumeMotionMove(SECOND_DISPLAY_ID);
4680
4681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4682 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
4683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4684 firstWindowInPrimary->assertNoEvents();
4685 secondWindowInPrimary->consumeMotionUp(SECOND_DISPLAY_ID);
4686}
4687
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004688TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4691 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004692
Vishnu Nair47074b82020-08-14 11:54:47 -07004693 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00004694 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07004695 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004696
4697 window->consumeFocusEvent(true);
4698
Prabir Pradhan678438e2023-04-13 19:32:51 +00004699 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004700
4701 // Window should receive key down event.
4702 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00004703
4704 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004705 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004706 mFakePolicy->assertUserActivityPoked();
4707}
4708
4709TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
4710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4712 "Fake Window", ADISPLAY_ID_DEFAULT);
4713
4714 window->setDisableUserActivity(true);
4715 window->setFocusable(true);
4716 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4717 setFocusedWindow(window);
4718
4719 window->consumeFocusEvent(true);
4720
4721 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4722
4723 // Window should receive key down event.
4724 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4725
4726 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004727 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00004728 mFakePolicy->assertUserActivityNotPoked();
4729}
4730
4731TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
4732 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4733 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4734 "Fake Window", ADISPLAY_ID_DEFAULT);
4735
4736 window->setFocusable(true);
4737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4738 setFocusedWindow(window);
4739
4740 window->consumeFocusEvent(true);
4741
4742 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4743 mDispatcher->waitForIdle();
4744
4745 // System key is not passed down
4746 window->assertNoEvents();
4747
4748 // Should have poked user activity
4749 mFakePolicy->assertUserActivityPoked();
4750}
4751
4752TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
4753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4755 "Fake Window", ADISPLAY_ID_DEFAULT);
4756
4757 window->setFocusable(true);
4758 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4759 setFocusedWindow(window);
4760
4761 window->consumeFocusEvent(true);
4762
4763 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4764 mDispatcher->waitForIdle();
4765
4766 // System key is not passed down
4767 window->assertNoEvents();
4768
4769 // Should have poked user activity
4770 mFakePolicy->assertUserActivityPoked();
4771}
4772
4773TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
4774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4775 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4776 "Fake Window", ADISPLAY_ID_DEFAULT);
4777
4778 window->setDisableUserActivity(true);
4779 window->setFocusable(true);
4780 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4781 setFocusedWindow(window);
4782
4783 window->consumeFocusEvent(true);
4784
4785 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
4786 mDispatcher->waitForIdle();
4787
4788 // System key is not passed down
4789 window->assertNoEvents();
4790
4791 // Should have poked user activity
4792 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004793}
4794
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004795TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
4796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4797 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4798 "Fake Window", ADISPLAY_ID_DEFAULT);
4799
4800 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4801
4802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4803 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4804 ADISPLAY_ID_DEFAULT, {100, 100}))
4805 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4806
4807 window->consumeMotionEvent(
4808 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
4809
4810 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00004811 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07004812 mFakePolicy->assertUserActivityPoked();
4813}
4814
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004815TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07004816 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004817 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4818 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004819
Arthur Hung72d8dc32020-03-28 00:48:39 +00004820 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004821
Prabir Pradhan678438e2023-04-13 19:32:51 +00004822 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004823 mDispatcher->waitForIdle();
4824
4825 window->assertNoEvents();
4826}
4827
4828// If a window is touchable, but does not have focus, it should receive motion events, but not keys
4829TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07004830 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4832 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004833
Arthur Hung72d8dc32020-03-28 00:48:39 +00004834 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004835
4836 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00004837 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004838 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00004839 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4840 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004841
4842 // Window should receive only the motion event
4843 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4844 window->assertNoEvents(); // Key event or focus event will not be received
4845}
4846
arthurhungea3f4fc2020-12-21 23:18:53 +08004847TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
4848 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4849
arthurhungea3f4fc2020-12-21 23:18:53 +08004850 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004851 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4852 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004853 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08004854
arthurhungea3f4fc2020-12-21 23:18:53 +08004855 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004856 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4857 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08004858 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08004859
4860 // Add the windows to the dispatcher
4861 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
4862
4863 PointF pointInFirst = {300, 200};
4864 PointF pointInSecond = {300, 600};
4865
4866 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004867 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4868 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4869 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004870 // Only the first window should get the down event
4871 firstWindow->consumeMotionDown();
4872 secondWindow->assertNoEvents();
4873
4874 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004875 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4876 ADISPLAY_ID_DEFAULT,
4877 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08004878 // The first window gets a move and the second a down
4879 firstWindow->consumeMotionMove();
4880 secondWindow->consumeMotionDown();
4881
4882 // Send pointer cancel to the second window
4883 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004884 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08004885 {pointInFirst, pointInSecond});
4886 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00004887 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08004888 // The first window gets move and the second gets cancel.
4889 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4890 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
4891
4892 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004893 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
4894 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08004895 // The first window gets up and the second gets nothing.
4896 firstWindow->consumeMotionUp();
4897 secondWindow->assertNoEvents();
4898}
4899
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004900TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
4901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4902
4903 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004904 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004905 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
4906 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
4907 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
4908 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
4909
Harry Cutts33476232023-01-30 19:57:29 +00004910 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00004911 window->assertNoEvents();
4912 mDispatcher->waitForIdle();
4913}
4914
chaviwd1c23182019-12-20 18:44:56 -08004915class FakeMonitorReceiver {
Michael Wright3a240c42019-12-10 20:53:41 +00004916public:
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004917 FakeMonitorReceiver(const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004918 int32_t displayId) {
Garfield Tan15601662020-09-22 15:32:38 -07004919 base::Result<std::unique_ptr<InputChannel>> channel =
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08004920 dispatcher->createInputMonitor(displayId, name, MONITOR_PID);
Garfield Tan15601662020-09-22 15:32:38 -07004921 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
Michael Wright3a240c42019-12-10 20:53:41 +00004922 }
4923
chaviwd1c23182019-12-20 18:44:56 -08004924 sp<IBinder> getToken() { return mInputReceiver->getToken(); }
4925
4926 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004927 mInputReceiver->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
4928 expectedFlags);
chaviwd1c23182019-12-20 18:44:56 -08004929 }
4930
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07004931 std::optional<int32_t> receiveEvent() { return mInputReceiver->receiveEvent(); }
4932
4933 void finishEvent(uint32_t consumeSeq) { return mInputReceiver->finishEvent(consumeSeq); }
4934
chaviwd1c23182019-12-20 18:44:56 -08004935 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004936 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
chaviwd1c23182019-12-20 18:44:56 -08004937 expectedDisplayId, expectedFlags);
4938 }
4939
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004940 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004941 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004942 expectedDisplayId, expectedFlags);
4943 }
4944
chaviwd1c23182019-12-20 18:44:56 -08004945 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004946 mInputReceiver->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
chaviwd1c23182019-12-20 18:44:56 -08004947 expectedDisplayId, expectedFlags);
4948 }
4949
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004950 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004951 mInputReceiver->consumeMotionEvent(
4952 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4953 WithDisplayId(expectedDisplayId),
4954 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004955 }
4956
Arthur Hungfbfa5722021-11-16 02:45:54 +00004957 void consumeMotionPointerDown(int32_t pointerIdx) {
4958 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
4959 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004960 mInputReceiver->consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00004961 /*expectedFlags=*/0);
Arthur Hungfbfa5722021-11-16 02:45:54 +00004962 }
4963
Evan Rosky84f07f02021-04-16 10:42:42 -07004964 MotionEvent* consumeMotion() {
4965 InputEvent* event = mInputReceiver->consume();
4966 if (!event) {
4967 ADD_FAILURE() << "No event was produced";
4968 return nullptr;
4969 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07004970 if (event->getType() != InputEventType::MOTION) {
4971 ADD_FAILURE() << "Expected MotionEvent, got " << *event;
Evan Rosky84f07f02021-04-16 10:42:42 -07004972 return nullptr;
4973 }
4974 return static_cast<MotionEvent*>(event);
4975 }
4976
chaviwd1c23182019-12-20 18:44:56 -08004977 void assertNoEvents() { mInputReceiver->assertNoEvents(); }
4978
4979private:
4980 std::unique_ptr<FakeInputReceiver> mInputReceiver;
Michael Wright3a240c42019-12-10 20:53:41 +00004981};
4982
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004983using InputDispatcherMonitorTest = InputDispatcherTest;
4984
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004985/**
4986 * Two entities that receive touch: A window, and a global monitor.
4987 * The touch goes to the window, and then the window disappears.
4988 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
4989 * for the monitor, as well.
4990 * 1. foregroundWindow
4991 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
4992 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004993TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4995 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004996 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004997
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08004998 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00004999
5000 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5002 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5003 {100, 200}))
5004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5005
5006 // Both the foreground window and the global monitor should receive the touch down
5007 window->consumeMotionDown();
5008 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5009
5010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5011 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5012 ADISPLAY_ID_DEFAULT, {110, 200}))
5013 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5014
5015 window->consumeMotionMove();
5016 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5017
5018 // Now the foreground window goes away
5019 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
5020 window->consumeMotionCancel();
5021 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5022
5023 // If more events come in, there will be no more foreground window to send them to. This will
5024 // cause a cancel for the monitor, as well.
5025 ASSERT_EQ(InputEventInjectionResult::FAILED,
5026 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5027 ADISPLAY_ID_DEFAULT, {120, 200}))
5028 << "Injection should fail because the window was removed";
5029 window->assertNoEvents();
5030 // Global monitor now gets the cancel
5031 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5032}
5033
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005034TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005036 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5037 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005038 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005039
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005040 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005041
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005043 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005045 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005046 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005047}
5048
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005049TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
5050 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005051
Chris Yea209fde2020-07-22 13:54:51 -07005052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005053 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5054 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005055 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Michael Wright3a240c42019-12-10 20:53:41 +00005056
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Michael Wright3a240c42019-12-10 20:53:41 +00005058 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005060 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005061 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005062
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005063 // Pilfer pointers from the monitor.
5064 // This should not do anything and the window should continue to receive events.
5065 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005066
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005068 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5069 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005070 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005071
5072 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5073 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005074}
5075
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005076TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005078 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5079 "Fake Window", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005080 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5081 window->setWindowOffset(20, 40);
5082 window->setWindowTransform(0, 1, -1, 0);
5083
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005084 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005085
5086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5087 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5089 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5090 MotionEvent* event = monitor.consumeMotion();
5091 // Even though window has transform, gesture monitor must not.
5092 ASSERT_EQ(ui::Transform(), event->getTransform());
5093}
5094
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005095TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005097 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005098
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005099 ASSERT_EQ(InputEventInjectionResult::FAILED,
Arthur Hungb3307ee2021-10-14 10:57:37 +00005100 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005101 << "Injection should fail if there is a monitor, but no touchable window";
5102 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005103}
5104
chaviw81e2bb92019-12-18 15:03:51 -08005105TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005107 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5108 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08005109
Arthur Hung72d8dc32020-03-28 00:48:39 +00005110 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
chaviw81e2bb92019-12-18 15:03:51 -08005111
5112 NotifyMotionArgs motionArgs =
5113 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5114 ADISPLAY_ID_DEFAULT);
5115
Prabir Pradhan678438e2023-04-13 19:32:51 +00005116 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08005117 // Window should receive motion down event.
5118 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5119
5120 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08005121 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08005122 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
5123 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5124 motionArgs.pointerCoords[0].getX() - 10);
5125
Prabir Pradhan678438e2023-04-13 19:32:51 +00005126 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005127 window->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005128 /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08005129}
5130
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005131/**
5132 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
5133 * the device default right away. In the test scenario, we check both the default value,
5134 * and the action of enabling / disabling.
5135 */
5136TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07005137 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005138 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5139 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08005140 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005141
5142 // Set focused application.
5143 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005144 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005145
5146 SCOPED_TRACE("Check default value of touch mode");
Arthur Hung72d8dc32020-03-28 00:48:39 +00005147 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005148 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005149 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005150
5151 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005152 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005153 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005154 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005155
5156 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005157 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005158 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005159 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07005160 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005161 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005162 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005163 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005164
5165 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07005166 window->setFocusable(false);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005167 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Harry Cutts33476232023-01-30 19:57:29 +00005168 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005169
5170 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08005171 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00005172 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00005173 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07005174 window->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005175 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005176 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00005177 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005178
5179 window->assertNoEvents();
5180}
5181
Gang Wange9087892020-01-07 12:17:14 -05005182TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005184 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5185 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05005186
5187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07005188 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05005189
Arthur Hung72d8dc32020-03-28 00:48:39 +00005190 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005191 setFocusedWindow(window);
5192
Harry Cutts33476232023-01-30 19:57:29 +00005193 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05005194
Prabir Pradhan678438e2023-04-13 19:32:51 +00005195 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
5196 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05005197
5198 InputEvent* event = window->consume();
5199 ASSERT_NE(event, nullptr);
5200
5201 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5202 ASSERT_NE(verified, nullptr);
5203 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
5204
5205 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
5206 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
5207 ASSERT_EQ(keyArgs.source, verified->source);
5208 ASSERT_EQ(keyArgs.displayId, verified->displayId);
5209
5210 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
5211
5212 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05005213 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005214 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05005215 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
5216 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
5217 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
5218 ASSERT_EQ(0, verifiedKey.repeatCount);
5219}
5220
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005221TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005223 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5224 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005225
5226 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5227
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005228 ui::Transform transform;
5229 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5230
5231 gui::DisplayInfo displayInfo;
5232 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5233 displayInfo.transform = transform;
5234
Patrick Williamsd828f302023-04-28 17:52:08 -05005235 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005236
Prabir Pradhan678438e2023-04-13 19:32:51 +00005237 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005238 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5239 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005240 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005241
5242 InputEvent* event = window->consume();
5243 ASSERT_NE(event, nullptr);
5244
5245 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
5246 ASSERT_NE(verified, nullptr);
5247 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
5248
5249 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
5250 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
5251 EXPECT_EQ(motionArgs.source, verified->source);
5252 EXPECT_EQ(motionArgs.displayId, verified->displayId);
5253
5254 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
5255
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07005256 const vec2 rawXY =
5257 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
5258 motionArgs.pointerCoords[0].getXYValue());
5259 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
5260 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005261 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005262 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08005263 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08005264 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
5265 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
5266}
5267
chaviw09c8d2d2020-08-24 15:48:26 -07005268/**
5269 * Ensure that separate calls to sign the same data are generating the same key.
5270 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
5271 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
5272 * tests.
5273 */
5274TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
5275 KeyEvent event = getTestKeyEvent();
5276 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5277
5278 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
5279 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
5280 ASSERT_EQ(hmac1, hmac2);
5281}
5282
5283/**
5284 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
5285 */
5286TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
5287 KeyEvent event = getTestKeyEvent();
5288 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
5289 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
5290
5291 verifiedEvent.deviceId += 1;
5292 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5293
5294 verifiedEvent.source += 1;
5295 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5296
5297 verifiedEvent.eventTimeNanos += 1;
5298 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5299
5300 verifiedEvent.displayId += 1;
5301 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5302
5303 verifiedEvent.action += 1;
5304 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5305
5306 verifiedEvent.downTimeNanos += 1;
5307 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5308
5309 verifiedEvent.flags += 1;
5310 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5311
5312 verifiedEvent.keyCode += 1;
5313 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5314
5315 verifiedEvent.scanCode += 1;
5316 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5317
5318 verifiedEvent.metaState += 1;
5319 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5320
5321 verifiedEvent.repeatCount += 1;
5322 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
5323}
5324
Vishnu Nair958da932020-08-21 17:12:37 -07005325TEST_F(InputDispatcherTest, SetFocusedWindow) {
5326 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5327 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005328 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005329 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005330 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005331 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5332
5333 // Top window is also focusable but is not granted focus.
5334 windowTop->setFocusable(true);
5335 windowSecond->setFocusable(true);
5336 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5337 setFocusedWindow(windowSecond);
5338
5339 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5341 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005342
5343 // Focused window should receive event.
5344 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5345 windowTop->assertNoEvents();
5346}
5347
5348TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
5349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5350 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005351 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005352 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5353
5354 window->setFocusable(true);
5355 // Release channel for window is no longer valid.
5356 window->releaseChannel();
5357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5358 setFocusedWindow(window);
5359
5360 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005361 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5362 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005363
5364 // window channel is invalid, so it should not receive any input event.
5365 window->assertNoEvents();
5366}
5367
5368TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
5369 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5370 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005371 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005372 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07005373 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5374
Vishnu Nair958da932020-08-21 17:12:37 -07005375 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5376 setFocusedWindow(window);
5377
5378 // Test inject a key down, should timeout.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005379 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
5380 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07005381
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005382 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07005383 window->assertNoEvents();
5384}
5385
5386TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
5387 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5388 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005390 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005392 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5393
5394 windowTop->setFocusable(true);
5395 windowSecond->setFocusable(true);
5396 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
5397 setFocusedWindow(windowTop);
5398 windowTop->consumeFocusEvent(true);
5399
Chavi Weingarten847e8512023-03-29 00:26:09 +00005400 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
5401 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005402 windowSecond->consumeFocusEvent(true);
5403 windowTop->consumeFocusEvent(false);
5404
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5406 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005407
5408 // Focused window should receive event.
5409 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
5410}
5411
Chavi Weingarten847e8512023-03-29 00:26:09 +00005412TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07005413 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5414 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005415 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005416 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005417 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005418 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5419
5420 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00005421 windowSecond->setFocusable(false);
5422 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Vishnu Nair958da932020-08-21 17:12:37 -07005423 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowTop, windowSecond}}});
Chavi Weingarten847e8512023-03-29 00:26:09 +00005424 setFocusedWindow(windowTop);
5425 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07005426
Chavi Weingarten847e8512023-03-29 00:26:09 +00005427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5428 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07005429
5430 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00005431 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07005432 windowSecond->assertNoEvents();
5433}
5434
5435TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
5436 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5437 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005438 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005439 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005440 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
5441 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07005442 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5443
5444 window->setFocusable(true);
5445 previousFocusedWindow->setFocusable(true);
5446 window->setVisible(false);
5447 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, previousFocusedWindow}}});
5448 setFocusedWindow(previousFocusedWindow);
5449 previousFocusedWindow->consumeFocusEvent(true);
5450
5451 // Requesting focus on invisible window takes focus from currently focused window.
5452 setFocusedWindow(window);
5453 previousFocusedWindow->consumeFocusEvent(false);
5454
5455 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00005457 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
5458 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07005459
5460 // Window does not get focus event or key down.
5461 window->assertNoEvents();
5462
5463 // Window becomes visible.
5464 window->setVisible(true);
5465 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5466
5467 // Window receives focus event.
5468 window->consumeFocusEvent(true);
5469 // Focused window receives key down.
5470 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5471}
5472
Vishnu Nair599f1412021-06-21 10:39:58 -07005473TEST_F(InputDispatcherTest, DisplayRemoved) {
5474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5475 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005476 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07005477 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5478
5479 // window is granted focus.
5480 window->setFocusable(true);
5481 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5482 setFocusedWindow(window);
5483 window->consumeFocusEvent(true);
5484
5485 // When a display is removed window loses focus.
5486 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
5487 window->consumeFocusEvent(false);
5488}
5489
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005490/**
5491 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
5492 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
5493 * of the 'slipperyEnterWindow'.
5494 *
5495 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
5496 * a way so that the touched location is no longer covered by the top window.
5497 *
5498 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
5499 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
5500 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
5501 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
5502 * with ACTION_DOWN).
5503 * Thus, the touch has been transferred from the top window into the bottom window, because the top
5504 * window moved itself away from the touched location and had Flag::SLIPPERY.
5505 *
5506 * Even though the top window moved away from the touched location, it is still obscuring the bottom
5507 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
5508 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
5509 *
5510 * In this test, we ensure that the event received by the bottom window has
5511 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
5512 */
5513TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005514 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005515 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005516
5517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5518 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
5519
5520 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005521 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08005522 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005523 // Make sure this one overlaps the bottom window
5524 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
5525 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
5526 // one. Windows with the same owner are not considered to be occluding each other.
5527 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
5528
5529 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005530 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005531 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
5532
5533 mDispatcher->setInputWindows(
5534 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5535
5536 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00005537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5538 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5539 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005540 slipperyExitWindow->consumeMotionDown();
5541 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
5542 mDispatcher->setInputWindows(
5543 {{ADISPLAY_ID_DEFAULT, {slipperyExitWindow, slipperyEnterWindow}}});
5544
Prabir Pradhan678438e2023-04-13 19:32:51 +00005545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
5546 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5547 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005548
5549 slipperyExitWindow->consumeMotionCancel();
5550
5551 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5552 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5553}
5554
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07005555/**
5556 * Two windows, one on the left and another on the right. The left window is slippery. The right
5557 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
5558 * touch moves from the left window into the right window, the gesture should continue to go to the
5559 * left window. Touch shouldn't slip because the right window can't receive touches. This test
5560 * reproduces a crash.
5561 */
5562TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
5563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5564
5565 sp<FakeWindowHandle> leftSlipperyWindow =
5566 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5567 leftSlipperyWindow->setSlippery(true);
5568 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
5569
5570 sp<FakeWindowHandle> rightDropTouchesWindow =
5571 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5572 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
5573 rightDropTouchesWindow->setDropInput(true);
5574
5575 mDispatcher->setInputWindows(
5576 {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}});
5577
5578 // Start touch in the left window
5579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5580 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5581 .build());
5582 leftSlipperyWindow->consumeMotionDown();
5583
5584 // And move it into the right window
5585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5586 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5587 .build());
5588
5589 // Since the right window isn't eligible to receive input, touch does not slip.
5590 // The left window continues to receive the gesture.
5591 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5592 rightDropTouchesWindow->assertNoEvents();
5593}
5594
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005595TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005596 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5598
5599 sp<FakeWindowHandle> leftWindow =
5600 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
5601 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005602 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005603
5604 sp<FakeWindowHandle> rightSpy =
5605 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
5606 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005607 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005608 rightSpy->setSpy(true);
5609 rightSpy->setTrustedOverlay(true);
5610
5611 sp<FakeWindowHandle> rightWindow =
5612 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
5613 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005614 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005615
5616 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {rightSpy, rightWindow, leftWindow}}});
5617
5618 // Touch in the left window
5619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5620 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5621 .build());
5622 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
5623 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005624 ASSERT_NO_FATAL_FAILURE(
5625 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005626
5627 // Touch another finger over the right windows
5628 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5629 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5630 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5631 .build());
5632 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
5633 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
5634 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
5635 mDispatcher->waitForIdle();
5636 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005637 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
5638 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005639
5640 // Release finger over left window. The UP actions are not treated as device interaction.
5641 // The windows that did not receive the UP pointer will receive MOVE events, but since this
5642 // is part of the UP action, we do not treat this as device interaction.
5643 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
5644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5645 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5646 .build());
5647 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
5648 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5649 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5650 mDispatcher->waitForIdle();
5651 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5652
5653 // Move remaining finger
5654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5655 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5656 .build());
5657 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
5658 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
5659 mDispatcher->waitForIdle();
5660 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005661 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005662
5663 // Release all fingers
5664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5665 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
5666 .build());
5667 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
5668 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
5669 mDispatcher->waitForIdle();
5670 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5671}
5672
5673TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
5674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5675
5676 sp<FakeWindowHandle> window =
5677 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5678 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00005679 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005680
5681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
5682 setFocusedWindow(window);
5683 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
5684
5685 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
5686 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
5687 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00005688 ASSERT_NO_FATAL_FAILURE(
5689 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00005690
5691 // The UP actions are not treated as device interaction.
5692 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
5693 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
5694 mDispatcher->waitForIdle();
5695 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
5696}
5697
Garfield Tan1c7bc862020-01-28 13:24:04 -08005698class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
5699protected:
5700 static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
5701 static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
5702
Chris Yea209fde2020-07-22 13:54:51 -07005703 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005704 sp<FakeWindowHandle> mWindow;
5705
5706 virtual void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +00005707 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhana41d2442023-04-20 21:30:40 +00005708 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy);
Harry Cutts101ee9b2023-07-06 18:04:14 +00005709 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Nergi Rahardi730cf3c2023-04-13 12:41:17 +09005710 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005711 ASSERT_EQ(OK, mDispatcher->start());
5712
5713 setUpWindow();
5714 }
5715
5716 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07005717 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005718 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005719
Vishnu Nair47074b82020-08-14 11:54:47 -07005720 mWindow->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005721 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005722 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005723 mWindow->consumeFocusEvent(true);
5724 }
5725
Chris Ye2ad95392020-09-01 13:44:44 -07005726 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005727 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005728 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005729 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005730 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005731
5732 // Window should receive key down event.
5733 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5734 }
5735
5736 void expectKeyRepeatOnce(int32_t repeatCount) {
5737 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
5738 InputEvent* repeatEvent = mWindow->consume();
5739 ASSERT_NE(nullptr, repeatEvent);
5740
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005741 ASSERT_EQ(InputEventType::KEY, repeatEvent->getType());
Garfield Tan1c7bc862020-01-28 13:24:04 -08005742
5743 KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
5744 uint32_t eventAction = repeatKeyEvent->getAction();
5745 EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
5746 EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
5747 }
5748
Chris Ye2ad95392020-09-01 13:44:44 -07005749 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08005750 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07005751 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08005752 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00005753 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005754
5755 // Window should receive key down event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005756 mWindow->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00005757 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005758 }
5759};
5760
5761TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
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 }
5766}
5767
5768TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00005769 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005770 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5771 expectKeyRepeatOnce(repeatCount);
5772 }
Harry Cutts33476232023-01-30 19:57:29 +00005773 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005774 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08005775 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5776 expectKeyRepeatOnce(repeatCount);
5777 }
5778}
5779
5780TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005781 sendAndConsumeKeyDown(/*deviceId=*/1);
5782 expectKeyRepeatOnce(/*repeatCount=*/1);
5783 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005784 mWindow->assertNoEvents();
5785}
5786
5787TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005788 sendAndConsumeKeyDown(/*deviceId=*/1);
5789 expectKeyRepeatOnce(/*repeatCount=*/1);
5790 sendAndConsumeKeyDown(/*deviceId=*/2);
5791 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005792 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00005793 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005794 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00005795 expectKeyRepeatOnce(/*repeatCount=*/2);
5796 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07005797 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00005798 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005799 mWindow->assertNoEvents();
5800}
5801
5802TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00005803 sendAndConsumeKeyDown(/*deviceId=*/1);
5804 expectKeyRepeatOnce(/*repeatCount=*/1);
5805 sendAndConsumeKeyDown(/*deviceId=*/2);
5806 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07005807 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00005808 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07005809 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08005810 mWindow->assertNoEvents();
5811}
5812
liushenxiang42232912021-05-21 20:24:09 +08005813TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
5814 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00005815 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005816 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08005817 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
5818 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
5819 mWindow->assertNoEvents();
5820}
5821
Garfield Tan1c7bc862020-01-28 13:24:04 -08005822TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005823 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005824 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005825 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5826 InputEvent* repeatEvent = mWindow->consume();
5827 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5828 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
5829 IdGenerator::getSource(repeatEvent->getId()));
5830 }
5831}
5832
5833TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00005834 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00005835 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08005836
5837 std::unordered_set<int32_t> idSet;
5838 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
5839 InputEvent* repeatEvent = mWindow->consume();
5840 ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
5841 int32_t id = repeatEvent->getId();
5842 EXPECT_EQ(idSet.end(), idSet.find(id));
5843 idSet.insert(id);
5844 }
5845}
5846
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005847/* Test InputDispatcher for MultiDisplay */
5848class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
5849public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005850 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005851 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08005852
Chris Yea209fde2020-07-22 13:54:51 -07005853 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005854 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005855 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005856
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005857 // Set focus window for primary display, but focused display would be second one.
5858 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07005859 windowInPrimary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005860 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005861 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005862 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08005863
Chris Yea209fde2020-07-22 13:54:51 -07005864 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005865 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005866 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005867 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005868 // Set focus display to second one.
5869 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
5870 // Set focus window for second display.
5871 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07005872 windowInSecondary->setFocusable(true);
Arthur Hung72d8dc32020-03-28 00:48:39 +00005873 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
Vishnu Nair958da932020-08-21 17:12:37 -07005874 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005875 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005876 }
5877
Prabir Pradhan3608aad2019-10-02 17:08:26 -07005878 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005879 InputDispatcherTest::TearDown();
5880
Chris Yea209fde2020-07-22 13:54:51 -07005881 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005882 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07005883 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005884 windowInSecondary.clear();
5885 }
5886
5887protected:
Chris Yea209fde2020-07-22 13:54:51 -07005888 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005889 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07005890 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005891 sp<FakeWindowHandle> windowInSecondary;
5892};
5893
5894TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
5895 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5897 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005899 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08005900 windowInSecondary->assertNoEvents();
5901
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005902 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5904 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005906 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005907 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08005908}
5909
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005910TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08005911 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5913 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005914 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005915 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08005916 windowInSecondary->assertNoEvents();
5917
5918 // Test inject a key down without display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005920 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08005921 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005922 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08005923
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08005924 // Remove all windows in secondary display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00005925 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
Arthur Hungb92218b2018-08-14 12:00:21 +08005926
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005927 // Old focus should receive a cancel event.
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07005928 windowInSecondary->consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_NONE,
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005929 AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08005930
5931 // Test inject a key down, should timeout because of no target window.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08005932 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDownNoRepeat(mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005933 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Arthur Hungb92218b2018-08-14 12:00:21 +08005934 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005935 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08005936 windowInSecondary->assertNoEvents();
5937}
5938
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005939// Test per-display input monitors for motion event.
5940TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08005941 FakeMonitorReceiver monitorInPrimary =
5942 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5943 FakeMonitorReceiver monitorInSecondary =
5944 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005945
5946 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5948 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
5949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005950 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005951 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005952 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005953 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005954
5955 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5957 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5958 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005959 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005960 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005961 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08005962 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005963
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08005964 // Lift up the touch from the second display
5965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5966 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
5967 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5968 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
5969 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
5970
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005971 // Test inject a non-pointer motion event.
5972 // If specific a display, it will dispatch to the focused window of particular display,
5973 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5975 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
5976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005977 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005978 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005979 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005980 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005981}
5982
5983// Test per-display input monitors for key event.
5984TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005985 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08005986 FakeMonitorReceiver monitorInPrimary =
5987 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5988 FakeMonitorReceiver monitorInSecondary =
5989 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005990
5991 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
5993 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005994 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08005995 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08005996 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08005997 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08005998}
5999
Vishnu Nair958da932020-08-21 17:12:37 -07006000TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
6001 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006002 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006003 secondWindowInPrimary->setFocusable(true);
6004 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowInPrimary, secondWindowInPrimary}}});
6005 setFocusedWindow(secondWindowInPrimary);
6006 windowInPrimary->consumeFocusEvent(false);
6007 secondWindowInPrimary->consumeFocusEvent(true);
6008
6009 // Test inject a key down.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
6011 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006012 windowInPrimary->assertNoEvents();
6013 windowInSecondary->assertNoEvents();
6014 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6015}
6016
Arthur Hungdfd528e2021-12-08 13:23:04 +00006017TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
6018 FakeMonitorReceiver monitorInPrimary =
6019 FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6020 FakeMonitorReceiver monitorInSecondary =
6021 FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
6022
6023 // Test touch down on primary display.
6024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6025 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
6026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6027 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6028 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6029
6030 // Test touch down on second display.
6031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6032 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
6033 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6034 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
6035 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
6036
6037 // Trigger cancel touch.
6038 mDispatcher->cancelCurrentTouch();
6039 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6040 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6041 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
6042 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
6043
6044 // Test inject a move motion event, no window/monitor should receive the event.
6045 ASSERT_EQ(InputEventInjectionResult::FAILED,
6046 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6047 ADISPLAY_ID_DEFAULT, {110, 200}))
6048 << "Inject motion event should return InputEventInjectionResult::FAILED";
6049 windowInPrimary->assertNoEvents();
6050 monitorInPrimary.assertNoEvents();
6051
6052 ASSERT_EQ(InputEventInjectionResult::FAILED,
6053 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6054 SECOND_DISPLAY_ID, {110, 200}))
6055 << "Inject motion event should return InputEventInjectionResult::FAILED";
6056 windowInSecondary->assertNoEvents();
6057 monitorInSecondary.assertNoEvents();
6058}
6059
Jackal Guof9696682018-10-05 12:23:23 +08006060class InputFilterTest : public InputDispatcherTest {
6061protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006062 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
6063 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08006064 NotifyMotionArgs motionArgs;
6065
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006066 motionArgs =
6067 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006068 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006069 motionArgs =
6070 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006071 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006072 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006073 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07006074 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006075 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08006076 } else {
6077 mFakePolicy->assertFilterInputEventWasNotCalled();
6078 }
6079 }
6080
6081 void testNotifyKey(bool expectToBeFiltered) {
6082 NotifyKeyArgs keyArgs;
6083
6084 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006085 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006086 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006087 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006088 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08006089
6090 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08006091 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08006092 } else {
6093 mFakePolicy->assertFilterInputEventWasNotCalled();
6094 }
6095 }
6096};
6097
6098// Test InputFilter for MotionEvent
6099TEST_F(InputFilterTest, MotionEvent_InputFilter) {
6100 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006101 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6102 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006103
6104 // Enable InputFilter
6105 mDispatcher->setInputFilterEnabled(true);
6106 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006107 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
6108 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006109
6110 // Disable InputFilter
6111 mDispatcher->setInputFilterEnabled(false);
6112 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006113 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
6114 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006115}
6116
6117// Test InputFilter for KeyEvent
6118TEST_F(InputFilterTest, KeyEvent_InputFilter) {
6119 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006120 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006121
6122 // Enable InputFilter
6123 mDispatcher->setInputFilterEnabled(true);
6124 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006125 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08006126
6127 // Disable InputFilter
6128 mDispatcher->setInputFilterEnabled(false);
6129 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006130 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08006131}
6132
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006133// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
6134// logical display coordinate space.
6135TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
6136 ui::Transform firstDisplayTransform;
6137 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6138 ui::Transform secondDisplayTransform;
6139 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
6140
6141 std::vector<gui::DisplayInfo> displayInfos(2);
6142 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
6143 displayInfos[0].transform = firstDisplayTransform;
6144 displayInfos[1].displayId = SECOND_DISPLAY_ID;
6145 displayInfos[1].transform = secondDisplayTransform;
6146
Patrick Williamsd828f302023-04-28 17:52:08 -05006147 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006148
6149 // Enable InputFilter
6150 mDispatcher->setInputFilterEnabled(true);
6151
6152 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00006153 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
6154 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07006155}
6156
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006157class InputFilterInjectionPolicyTest : public InputDispatcherTest {
6158protected:
6159 virtual void SetUp() override {
6160 InputDispatcherTest::SetUp();
6161
6162 /**
6163 * We don't need to enable input filter to test the injected event policy, but we enabled it
6164 * here to make the tests more realistic, since this policy only matters when inputfilter is
6165 * on.
6166 */
6167 mDispatcher->setInputFilterEnabled(true);
6168
6169 std::shared_ptr<InputApplicationHandle> application =
6170 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006171 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
6172 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006173
6174 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6175 mWindow->setFocusable(true);
6176 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6177 setFocusedWindow(mWindow);
6178 mWindow->consumeFocusEvent(true);
6179 }
6180
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006181 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6182 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006183 KeyEvent event;
6184
6185 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6186 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
6187 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00006188 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006189 const int32_t additionalPolicyFlags =
6190 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
6191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006192 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006193 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006194 policyFlags | additionalPolicyFlags));
6195
6196 InputEvent* received = mWindow->consume();
6197 ASSERT_NE(nullptr, received);
6198 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006199 ASSERT_EQ(received->getType(), InputEventType::KEY);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006200 KeyEvent& keyEvent = static_cast<KeyEvent&>(*received);
6201 ASSERT_EQ(flags, keyEvent.getFlags());
6202 }
6203
6204 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
6205 int32_t flags) {
6206 MotionEvent event;
6207 PointerProperties pointerProperties[1];
6208 PointerCoords pointerCoords[1];
6209 pointerProperties[0].clear();
6210 pointerProperties[0].id = 0;
6211 pointerCoords[0].clear();
6212 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
6213 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
6214
6215 ui::Transform identityTransform;
6216 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6217 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
6218 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6219 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
6220 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07006221 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07006222 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006223 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006224
6225 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
6226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00006227 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00006228 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006229 policyFlags | additionalPolicyFlags));
6230
6231 InputEvent* received = mWindow->consume();
6232 ASSERT_NE(nullptr, received);
6233 ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006234 ASSERT_EQ(received->getType(), InputEventType::MOTION);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006235 MotionEvent& motionEvent = static_cast<MotionEvent&>(*received);
6236 ASSERT_EQ(flags, motionEvent.getFlags());
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006237 }
6238
6239private:
6240 sp<FakeWindowHandle> mWindow;
6241};
6242
6243TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006244 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
6245 // filter. Without it, the event will no different from a regularly injected event, and the
6246 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00006247 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
6248 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006249}
6250
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006251TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006252 testInjectedKey(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 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
6255}
6256
6257TEST_F(InputFilterInjectionPolicyTest,
6258 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
6259 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00006260 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00006261 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006262}
6263
6264TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00006265 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
6266 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00006267}
6268
chaviwfd6d3512019-03-25 13:23:49 -07006269class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006270 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07006271 InputDispatcherTest::SetUp();
6272
Chris Yea209fde2020-07-22 13:54:51 -07006273 std::shared_ptr<FakeApplicationHandle> application =
6274 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006275 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006276 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006277 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07006278
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006279 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006280 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006281 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07006282
6283 // Set focused application.
6284 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006285 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07006286
6287 // Expect one focus window exist in display.
Arthur Hung72d8dc32020-03-28 00:48:39 +00006288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006289 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006290 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07006291 }
6292
Prabir Pradhan3608aad2019-10-02 17:08:26 -07006293 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07006294 InputDispatcherTest::TearDown();
6295
6296 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006297 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07006298 }
6299
6300protected:
6301 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006302 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006303 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07006304};
6305
6306// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6307// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
6308// the onPointerDownOutsideFocus callback.
6309TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006311 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6312 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006313 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006314 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006315
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006316 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07006317 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
6318}
6319
6320// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
6321// DOWN on the window that doesn't have focus. Ensure no window received the
6322// onPointerDownOutsideFocus callback.
6323TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006325 injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006326 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006327 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006328
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006329 ASSERT_TRUE(mDispatcher->waitForIdle());
6330 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006331}
6332
6333// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
6334// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
6335TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6337 injectKeyDownNoRepeat(mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006338 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006339 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07006340
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006341 ASSERT_TRUE(mDispatcher->waitForIdle());
6342 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006343}
6344
6345// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
6346// DOWN on the window that already has focus. Ensure no window received the
6347// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006348TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08006350 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07006351 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006352 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07006353 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07006354
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08006355 ASSERT_TRUE(mDispatcher->waitForIdle());
6356 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07006357}
6358
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006359// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
6360// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
6361TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
6362 const MotionEvent event =
6363 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6364 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006365 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08006366 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
6367 .build();
6368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
6369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6370 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6371
6372 ASSERT_TRUE(mDispatcher->waitForIdle());
6373 mFakePolicy->assertOnPointerDownWasNotCalled();
6374 // Ensure that the unfocused window did not receive any FOCUS events.
6375 mUnfocusedWindow->assertNoEvents();
6376}
6377
chaviwaf87b3e2019-10-01 16:59:28 -07006378// These tests ensures we can send touch events to a single client when there are multiple input
6379// windows that point to the same client token.
6380class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
6381 virtual void SetUp() override {
6382 InputDispatcherTest::SetUp();
6383
Chris Yea209fde2020-07-22 13:54:51 -07006384 std::shared_ptr<FakeApplicationHandle> application =
6385 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006386 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
6387 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07006388 mWindow1->setFrame(Rect(0, 0, 100, 100));
6389
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006390 mWindow2 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 2",
6391 ADISPLAY_ID_DEFAULT, mWindow1->getToken());
chaviwaf87b3e2019-10-01 16:59:28 -07006392 mWindow2->setFrame(Rect(100, 100, 200, 200));
6393
Arthur Hung72d8dc32020-03-28 00:48:39 +00006394 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
chaviwaf87b3e2019-10-01 16:59:28 -07006395 }
6396
6397protected:
6398 sp<FakeWindowHandle> mWindow1;
6399 sp<FakeWindowHandle> mWindow2;
6400
6401 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05006402 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07006403 vec2 vals = windowInfo->transform.transform(point.x, point.y);
6404 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07006405 }
6406
6407 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
6408 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006409 const std::string name = window->getName();
chaviwaf87b3e2019-10-01 16:59:28 -07006410 InputEvent* event = window->consume();
6411
6412 ASSERT_NE(nullptr, event) << name.c_str()
6413 << ": consumer should have returned non-NULL event.";
6414
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07006415 ASSERT_EQ(InputEventType::MOTION, event->getType())
6416 << name.c_str() << ": expected MotionEvent, got " << *event;
chaviwaf87b3e2019-10-01 16:59:28 -07006417
6418 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006419 assertMotionAction(expectedAction, motionEvent.getAction());
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08006420 ASSERT_EQ(points.size(), motionEvent.getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07006421
6422 for (size_t i = 0; i < points.size(); i++) {
6423 float expectedX = points[i].x;
6424 float expectedY = points[i].y;
6425
6426 EXPECT_EQ(expectedX, motionEvent.getX(i))
6427 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
6428 << ", got " << motionEvent.getX(i);
6429 EXPECT_EQ(expectedY, motionEvent.getY(i))
6430 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
6431 << ", got " << motionEvent.getY(i);
6432 }
6433 }
chaviw9eaa22c2020-07-01 16:21:27 -07006434
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006435 void touchAndAssertPositions(int32_t action, const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07006436 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00006437 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
6438 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07006439
6440 // Always consume from window1 since it's the window that has the InputReceiver
6441 consumeMotionEvent(mWindow1, action, expectedPoints);
6442 }
chaviwaf87b3e2019-10-01 16:59:28 -07006443};
6444
6445TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
6446 // Touch Window 1
6447 PointF touchedPoint = {10, 10};
6448 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006449 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006450
6451 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006452 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006453
6454 // Touch Window 2
6455 touchedPoint = {150, 150};
6456 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006457 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006458}
6459
chaviw9eaa22c2020-07-01 16:21:27 -07006460TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
6461 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07006462 mWindow2->setWindowScale(0.5f, 0.5f);
6463
6464 // Touch Window 1
6465 PointF touchedPoint = {10, 10};
6466 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006467 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006468 // Release touch on Window 1
chaviw9eaa22c2020-07-01 16:21:27 -07006469 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006470
6471 // Touch Window 2
6472 touchedPoint = {150, 150};
6473 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
chaviw9eaa22c2020-07-01 16:21:27 -07006474 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
6475 touchAndAssertPositions(AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006476
chaviw9eaa22c2020-07-01 16:21:27 -07006477 // Update the transform so rotation is set
6478 mWindow2->setWindowTransform(0, -1, 1, 0);
6479 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
6480 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07006481}
6482
chaviw9eaa22c2020-07-01 16:21:27 -07006483TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006484 mWindow2->setWindowScale(0.5f, 0.5f);
6485
6486 // Touch Window 1
6487 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6488 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006489 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006490
6491 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006492 touchedPoints.push_back(PointF{150, 150});
6493 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006494 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006495
chaviw9eaa22c2020-07-01 16:21:27 -07006496 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006497 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006498 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006499
chaviw9eaa22c2020-07-01 16:21:27 -07006500 // Update the transform so rotation is set for Window 2
6501 mWindow2->setWindowTransform(0, -1, 1, 0);
6502 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006503 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006504}
6505
chaviw9eaa22c2020-07-01 16:21:27 -07006506TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006507 mWindow2->setWindowScale(0.5f, 0.5f);
6508
6509 // Touch Window 1
6510 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6511 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006512 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006513
6514 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006515 touchedPoints.push_back(PointF{150, 150});
6516 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006517
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006518 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006519
6520 // Move both windows
6521 touchedPoints = {{20, 20}, {175, 175}};
6522 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6523 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6524
chaviw9eaa22c2020-07-01 16:21:27 -07006525 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006526
chaviw9eaa22c2020-07-01 16:21:27 -07006527 // Release Window 2
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006528 touchAndAssertPositions(POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006529 expectedPoints.pop_back();
6530
6531 // Touch Window 2
6532 mWindow2->setWindowTransform(0, -1, 1, 0);
6533 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006534 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07006535
6536 // Move both windows
6537 touchedPoints = {{20, 20}, {175, 175}};
6538 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6539 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6540
6541 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006542}
6543
6544TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
6545 mWindow1->setWindowScale(0.5f, 0.5f);
6546
6547 // Touch Window 1
6548 std::vector<PointF> touchedPoints = {PointF{10, 10}};
6549 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
chaviw9eaa22c2020-07-01 16:21:27 -07006550 touchAndAssertPositions(AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006551
6552 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07006553 touchedPoints.push_back(PointF{150, 150});
6554 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006555
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006556 touchAndAssertPositions(POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006557
6558 // Move both windows
6559 touchedPoints = {{20, 20}, {175, 175}};
6560 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
6561 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
6562
chaviw9eaa22c2020-07-01 16:21:27 -07006563 touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00006564}
6565
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07006566/**
6567 * When one of the windows is slippery, the touch should not slip into the other window with the
6568 * same input channel.
6569 */
6570TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
6571 mWindow1->setSlippery(true);
6572 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6573
6574 // Touch down in window 1
6575 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6576 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6577 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
6578
6579 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
6580 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
6581 // getting generated.
6582 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6583 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6584
6585 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
6586}
6587
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07006588/**
6589 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
6590 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
6591 * that the pointer is hovering over may have a different transform.
6592 */
6593TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
6594 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});
6595
6596 // Start hover in window 1
6597 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN,
6598 ADISPLAY_ID_DEFAULT, {{50, 50}}));
6599 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6600 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
6601
6602 // Move hover to window 2.
6603 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6604 ADISPLAY_ID_DEFAULT, {{150, 150}}));
6605
6606 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
6607 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
6608 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
6609}
6610
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006611class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
6612 virtual void SetUp() override {
6613 InputDispatcherTest::SetUp();
6614
Chris Yea209fde2020-07-22 13:54:51 -07006615 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006616 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006617 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
6618 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006619 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006620 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07006621 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006622
6623 // Set focused application.
6624 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
6625
6626 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07006627 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006628 mWindow->consumeFocusEvent(true);
6629 }
6630
6631 virtual void TearDown() override {
6632 InputDispatcherTest::TearDown();
6633 mWindow.clear();
6634 }
6635
6636protected:
Chris Yea209fde2020-07-22 13:54:51 -07006637 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006638 sp<FakeWindowHandle> mWindow;
6639 static constexpr PointF WINDOW_LOCATION = {20, 20};
6640
6641 void tapOnWindow() {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006643 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6644 WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006646 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6647 WINDOW_LOCATION));
6648 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006649
6650 sp<FakeWindowHandle> addSpyWindow() {
6651 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006652 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006653 spy->setTrustedOverlay(true);
6654 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08006655 spy->setSpy(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006656 spy->setDispatchingTimeout(30ms);
6657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, mWindow}}});
6658 return spy;
6659 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006660};
6661
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006662// Send a tap and respond, which should not cause an ANR.
6663TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
6664 tapOnWindow();
6665 mWindow->consumeMotionDown();
6666 mWindow->consumeMotionUp();
6667 ASSERT_TRUE(mDispatcher->waitForIdle());
6668 mFakePolicy->assertNotifyAnrWasNotCalled();
6669}
6670
6671// Send a regular key and respond, which should not cause an ANR.
6672TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006674 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
6675 ASSERT_TRUE(mDispatcher->waitForIdle());
6676 mFakePolicy->assertNotifyAnrWasNotCalled();
6677}
6678
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006679TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
6680 mWindow->setFocusable(false);
6681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6682 mWindow->consumeFocusEvent(false);
6683
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006684 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006685 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006686 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00006687 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05006689 // Key will not go to window because we have no focused window.
6690 // The 'no focused window' ANR timer should start instead.
6691
6692 // Now, the focused application goes away.
6693 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
6694 // The key should get dropped and there should be no ANR.
6695
6696 ASSERT_TRUE(mDispatcher->waitForIdle());
6697 mFakePolicy->assertNotifyAnrWasNotCalled();
6698}
6699
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006700// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006701// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
6702// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006703TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006705 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6706 WINDOW_LOCATION));
6707
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006708 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
6709 ASSERT_TRUE(sequenceNum);
6710 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006711 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006712
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006713 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006714 mWindow->consumeMotionEvent(
6715 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006716 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006717 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006718}
6719
6720// Send a key to the app and have the app not respond right away.
6721TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
6722 // Inject a key, and don't respond - expect that ANR is called.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08006723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(mDispatcher));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006724 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent();
6725 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006726 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006727 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07006728 ASSERT_TRUE(mDispatcher->waitForIdle());
6729}
6730
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006731// We have a focused application, but no focused window
6732TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006733 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006734 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6735 mWindow->consumeFocusEvent(false);
6736
6737 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006739 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6740 WINDOW_LOCATION));
6741 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
6742 mDispatcher->waitForIdle();
6743 mFakePolicy->assertNotifyAnrWasNotCalled();
6744
6745 // Once a focused event arrives, we get an ANR for this application
6746 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6747 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006748 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006749 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006750 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006751 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006752 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07006753 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006754 ASSERT_TRUE(mDispatcher->waitForIdle());
6755}
6756
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006757/**
6758 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
6759 * there will not be an ANR.
6760 */
6761TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
6762 mWindow->setFocusable(false);
6763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6764 mWindow->consumeFocusEvent(false);
6765
6766 KeyEvent event;
6767 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
6768 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
6769
6770 // Define a valid key down event that is stale (too old).
6771 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00006772 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00006773 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006774
6775 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
6776
6777 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006778 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08006779 InputEventInjectionSync::WAIT_FOR_RESULT,
6780 INJECT_EVENT_TIMEOUT, policyFlags);
6781 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
6782 << "Injection should fail because the event is stale";
6783
6784 ASSERT_TRUE(mDispatcher->waitForIdle());
6785 mFakePolicy->assertNotifyAnrWasNotCalled();
6786 mWindow->assertNoEvents();
6787}
6788
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006789// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006790// Make sure that we don't notify policy twice about the same ANR.
6791TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006792 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006793 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6794 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006795
6796 // Once a focused event arrives, we get an ANR for this application
6797 // We specify the injection timeout to be smaller than the application timeout, to ensure that
6798 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006799 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006800 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006801 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006802 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Vishnu Naire4df8752022-09-08 09:17:55 -07006803 const std::chrono::duration appTimeout =
6804 mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6805 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006806
Vishnu Naire4df8752022-09-08 09:17:55 -07006807 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006808 // ANR should not be raised again. It is up to policy to do that if it desires.
6809 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006810
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006811 // If we now get a focused window, the ANR should stop, but the policy handles that via
6812 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006813 ASSERT_TRUE(mDispatcher->waitForIdle());
6814}
6815
6816// We have a focused application, but no focused window
6817TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07006818 mWindow->setFocusable(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006819 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
6820 mWindow->consumeFocusEvent(false);
6821
6822 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006823 const InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00006824 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07006825 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006826 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006827
Vishnu Naire4df8752022-09-08 09:17:55 -07006828 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
6829 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006830
6831 // Future focused events get dropped right away
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006832 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006833 ASSERT_TRUE(mDispatcher->waitForIdle());
6834 mWindow->assertNoEvents();
6835}
6836
6837/**
6838 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
6839 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
6840 * If we process 1 of the events, but ANR on the second event with the same timestamp,
6841 * the ANR mechanism should still work.
6842 *
6843 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
6844 * DOWN event, while not responding on the second one.
6845 */
6846TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
6847 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
6848 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, 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 // Now send ACTION_UP, with identical timestamp
6855 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6856 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
6857 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
6858 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006859 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006860
6861 // We have now sent down and up. Let's consume first event and then ANR on the second.
6862 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6863 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006864 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006865}
6866
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006867// A spy window can receive an ANR
6868TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
6869 sp<FakeWindowHandle> spy = addSpyWindow();
6870
6871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6872 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6873 WINDOW_LOCATION));
6874 mWindow->consumeMotionDown();
6875
6876 std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN
6877 ASSERT_TRUE(sequenceNum);
6878 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006879 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006880
6881 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08006882 spy->consumeMotionEvent(
6883 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006884 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006885 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006886}
6887
6888// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006889// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006890TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
6891 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006892
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6894 injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006895 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006897
6898 // Stuck on the ACTION_UP
6899 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006900 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006901
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006902 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006903 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006904 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6905 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006906
6907 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6908 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006909 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006910 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006911 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006912}
6913
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006914// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006915// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006916TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
6917 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006918
6919 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006920 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6921 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006922
6923 mWindow->consumeMotionDown();
6924 // Stuck on the ACTION_UP
6925 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006926 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006927
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006928 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006929 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006930 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6931 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006932
6933 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
6934 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006935 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006936 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006937 spy->assertNoEvents();
6938}
6939
6940TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
6941 mDispatcher->setMonitorDispatchingTimeoutForTest(30ms);
6942
6943 FakeMonitorReceiver monitor = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6944
6945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6946 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6947 WINDOW_LOCATION));
6948
6949 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6950 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
6951 ASSERT_TRUE(consumeSeq);
6952
Prabir Pradhanedd96402022-02-15 01:46:16 -08006953 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006954
6955 monitor.finishEvent(*consumeSeq);
6956 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6957
6958 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08006959 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006960}
6961
6962// If a window is unresponsive, then you get anr. if the window later catches up and starts to
6963// process events, you don't get an anr. When the window later becomes unresponsive again, you
6964// get an ANR again.
6965// 1. tap -> block on ACTION_UP -> receive ANR
6966// 2. consume all pending events (= queue becomes healthy again)
6967// 3. tap again -> block on ACTION_UP again -> receive ANR second time
6968TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
6969 tapOnWindow();
6970
6971 mWindow->consumeMotionDown();
6972 // Block on ACTION_UP
6973 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006974 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006975 mWindow->consumeMotionUp(); // Now the connection should be healthy again
6976 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006977 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006978 mWindow->assertNoEvents();
6979
6980 tapOnWindow();
6981 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006982 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006983 mWindow->consumeMotionUp();
6984
6985 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08006986 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006987 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006988 mWindow->assertNoEvents();
6989}
6990
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05006991// If a connection remains unresponsive for a while, make sure policy is only notified once about
6992// it.
6993TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07006995 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6996 WINDOW_LOCATION));
6997
6998 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08006999 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007000 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007001 // 'notifyConnectionUnresponsive' should only be called once per connection
7002 mFakePolicy->assertNotifyAnrWasNotCalled();
7003 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007004 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08007005 mWindow->consumeMotionEvent(
7006 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007007 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007008 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08007009 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007010 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007011}
7012
7013/**
7014 * If a window is processing a motion event, and then a key event comes in, the key event should
7015 * not to to the focused window until the motion is processed.
7016 *
7017 * Warning!!!
7018 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7019 * and the injection timeout that we specify when injecting the key.
7020 * We must have the injection timeout (10ms) be smaller than
7021 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7022 *
7023 * If that value changes, this test should also change.
7024 */
7025TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
7026 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7027 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7028
7029 tapOnWindow();
7030 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7031 ASSERT_TRUE(downSequenceNum);
7032 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7033 ASSERT_TRUE(upSequenceNum);
7034 // Don't finish the events yet, and send a key
7035 // Injection will "succeed" because we will eventually give up and send the key to the focused
7036 // window even if motions are still being processed. But because the injection timeout is short,
7037 // we will receive INJECTION_TIMED_OUT as the result.
7038
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007039 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007040 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007041 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007042 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007043 // Key will not be sent to the window, yet, because the window is still processing events
7044 // and the key remains pending, waiting for the touch events to be processed
7045 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7046 ASSERT_FALSE(keySequenceNum);
7047
7048 std::this_thread::sleep_for(500ms);
7049 // if we wait long enough though, dispatcher will give up, and still send the key
7050 // to the focused window, even though we have not yet finished the motion event
7051 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7052 mWindow->finishEvent(*downSequenceNum);
7053 mWindow->finishEvent(*upSequenceNum);
7054}
7055
7056/**
7057 * If a window is processing a motion event, and then a key event comes in, the key event should
7058 * not go to the focused window until the motion is processed.
7059 * If then a new motion comes in, then the pending key event should be going to the currently
7060 * focused window right away.
7061 */
7062TEST_F(InputDispatcherSingleWindowAnr,
7063 PendingKey_IsDroppedWhileMotionIsProcessedAndNewTouchComesIn) {
7064 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
7065 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
7066
7067 tapOnWindow();
7068 std::optional<uint32_t> downSequenceNum = mWindow->receiveEvent();
7069 ASSERT_TRUE(downSequenceNum);
7070 std::optional<uint32_t> upSequenceNum = mWindow->receiveEvent();
7071 ASSERT_TRUE(upSequenceNum);
7072 // Don't finish the events yet, and send a key
7073 // Injection is async, so it will succeed
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007075 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7076 InputEventInjectionSync::NONE));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007077 // At this point, key is still pending, and should not be sent to the application yet.
7078 std::optional<uint32_t> keySequenceNum = mWindow->receiveEvent();
7079 ASSERT_FALSE(keySequenceNum);
7080
7081 // Now tap down again. It should cause the pending key to go to the focused window right away.
7082 tapOnWindow();
7083 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT); // it doesn't matter that we haven't ack'd
7084 // the other events yet. We can finish events in any order.
7085 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
7086 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
7087 mWindow->consumeMotionDown();
7088 mWindow->consumeMotionUp();
7089 mWindow->assertNoEvents();
7090}
7091
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007092/**
7093 * Send an event to the app and have the app not respond right away.
7094 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
7095 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
7096 * At some point, the window becomes responsive again.
7097 * Ensure that subsequent events get dropped, and the next gesture is delivered.
7098 */
7099TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
7100 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7101 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
7102 .build());
7103
7104 std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN
7105 ASSERT_TRUE(sequenceNum);
7106 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
7107 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
7108
7109 mWindow->finishEvent(*sequenceNum);
7110 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7111 ASSERT_TRUE(mDispatcher->waitForIdle());
7112 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
7113
7114 // Now that the window is responsive, let's continue the gesture.
7115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7116 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7117 .build());
7118
7119 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7120 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7121 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7122 .build());
7123
7124 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
7125 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7126 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
7127 .build());
7128 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7129 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
7130 .build());
7131 // We already canceled this pointer, so the window shouldn't get any new events.
7132 mWindow->assertNoEvents();
7133
7134 // Start another one.
7135 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7136 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
7137 .build());
7138 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7139}
7140
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007141class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
7142 virtual void SetUp() override {
7143 InputDispatcherTest::SetUp();
7144
Chris Yea209fde2020-07-22 13:54:51 -07007145 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007146 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007147 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
7148 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007149 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007150 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007151 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007152
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007153 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
7154 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007155 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007156 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007157
7158 // Set focused application.
7159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07007160 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007161
7162 // Expect one focus window exist in display.
7163 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007164 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007165 mFocusedWindow->consumeFocusEvent(true);
7166 }
7167
7168 virtual void TearDown() override {
7169 InputDispatcherTest::TearDown();
7170
7171 mUnfocusedWindow.clear();
7172 mFocusedWindow.clear();
7173 }
7174
7175protected:
Chris Yea209fde2020-07-22 13:54:51 -07007176 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007177 sp<FakeWindowHandle> mUnfocusedWindow;
7178 sp<FakeWindowHandle> mFocusedWindow;
7179 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
7180 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
7181 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
7182
7183 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
7184
7185 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
7186
7187private:
7188 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007190 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7191 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007193 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7194 location));
7195 }
7196};
7197
7198// If we have 2 windows that are both unresponsive, the one with the shortest timeout
7199// should be ANR'd first.
7200TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007202 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7203 FOCUSED_WINDOW_LOCATION))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007205 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007206 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007207 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007208 // We consumed all events, so no ANR
7209 ASSERT_TRUE(mDispatcher->waitForIdle());
7210 mFakePolicy->assertNotifyAnrWasNotCalled();
7211
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007213 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7214 FOCUSED_WINDOW_LOCATION));
7215 std::optional<uint32_t> unfocusedSequenceNum = mUnfocusedWindow->receiveEvent();
7216 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007217
7218 const std::chrono::duration timeout =
7219 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007220 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007221 // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event
7222 // sequence to make it consistent
7223 mFocusedWindow->consumeMotionCancel();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007224 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007225 mFocusedWindow->consumeMotionDown();
7226 // This cancel is generated because the connection was unresponsive
7227 mFocusedWindow->consumeMotionCancel();
7228 mFocusedWindow->assertNoEvents();
7229 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007230 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007231 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7232 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007233 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007234}
7235
7236// If we have 2 windows with identical timeouts that are both unresponsive,
7237// it doesn't matter which order they should have ANR.
7238// But we should receive ANR for both.
7239TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
7240 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007241 mUnfocusedWindow->setDispatchingTimeout(
7242 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7244
7245 tapOnFocusedWindow();
7246 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007247 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007248 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
7249 mFocusedWindow->getDispatchingTimeout(
7250 DISPATCHING_TIMEOUT)),
7251 mFakePolicy->getUnresponsiveWindowToken(0ms)};
7252
7253 ASSERT_THAT(anrConnectionTokens,
7254 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7255 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007256
7257 ASSERT_TRUE(mDispatcher->waitForIdle());
7258 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007259
7260 mFocusedWindow->consumeMotionDown();
7261 mFocusedWindow->consumeMotionUp();
7262 mUnfocusedWindow->consumeMotionOutside();
7263
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007264 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
7265 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007266
7267 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007268 ASSERT_THAT(responsiveTokens,
7269 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
7270 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007271 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007272}
7273
7274// If a window is already not responding, the second tap on the same window should be ignored.
7275// We should also log an error to account for the dropped event (not tested here).
7276// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
7277TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
7278 tapOnFocusedWindow();
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007279 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007280 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007281 // Receive the events, but don't respond
7282 std::optional<uint32_t> downEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_DOWN
7283 ASSERT_TRUE(downEventSequenceNum);
7284 std::optional<uint32_t> upEventSequenceNum = mFocusedWindow->receiveEvent(); // ACTION_UP
7285 ASSERT_TRUE(upEventSequenceNum);
7286 const std::chrono::duration timeout =
7287 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007288 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007289
7290 // Tap once again
7291 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007292 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007293 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7294 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007295 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007296 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7297 FOCUSED_WINDOW_LOCATION));
7298 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
7299 // valid touch target
7300 mUnfocusedWindow->assertNoEvents();
7301
7302 // Consume the first tap
7303 mFocusedWindow->finishEvent(*downEventSequenceNum);
7304 mFocusedWindow->finishEvent(*upEventSequenceNum);
7305 ASSERT_TRUE(mDispatcher->waitForIdle());
7306 // The second tap did not go to the focused window
7307 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007308 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08007309 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7310 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007311 mFakePolicy->assertNotifyAnrWasNotCalled();
7312}
7313
7314// If you tap outside of all windows, there will not be ANR
7315TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007317 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7318 LOCATION_OUTSIDE_ALL_WINDOWS));
7319 ASSERT_TRUE(mDispatcher->waitForIdle());
7320 mFakePolicy->assertNotifyAnrWasNotCalled();
7321}
7322
7323// Since the focused window is paused, tapping on it should not produce any events
7324TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
7325 mFocusedWindow->setPaused(true);
7326 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mUnfocusedWindow, mFocusedWindow}}});
7327
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007329 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7330 FOCUSED_WINDOW_LOCATION));
7331
7332 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
7333 ASSERT_TRUE(mDispatcher->waitForIdle());
7334 // Should not ANR because the window is paused, and touches shouldn't go to it
7335 mFakePolicy->assertNotifyAnrWasNotCalled();
7336
7337 mFocusedWindow->assertNoEvents();
7338 mUnfocusedWindow->assertNoEvents();
7339}
7340
7341/**
7342 * If a window is processing a motion event, and then a key event comes in, the key event should
7343 * not to to the focused window until the motion is processed.
7344 * If a different window becomes focused at this time, the key should go to that window instead.
7345 *
7346 * Warning!!!
7347 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
7348 * and the injection timeout that we specify when injecting the key.
7349 * We must have the injection timeout (10ms) be smaller than
7350 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
7351 *
7352 * If that value changes, this test should also change.
7353 */
7354TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
7355 // Set a long ANR timeout to prevent it from triggering
7356 mFocusedWindow->setDispatchingTimeout(2s);
7357 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7358
7359 tapOnUnfocusedWindow();
7360 std::optional<uint32_t> downSequenceNum = mUnfocusedWindow->receiveEvent();
7361 ASSERT_TRUE(downSequenceNum);
7362 std::optional<uint32_t> upSequenceNum = mUnfocusedWindow->receiveEvent();
7363 ASSERT_TRUE(upSequenceNum);
7364 // Don't finish the events yet, and send a key
7365 // Injection will succeed because we will eventually give up and send the key to the focused
7366 // window even if motions are still being processed.
7367
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007368 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007369 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007370 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007372 // Key will not be sent to the window, yet, because the window is still processing events
7373 // and the key remains pending, waiting for the touch events to be processed
7374 std::optional<uint32_t> keySequenceNum = mFocusedWindow->receiveEvent();
7375 ASSERT_FALSE(keySequenceNum);
7376
7377 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07007378 mFocusedWindow->setFocusable(false);
7379 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007380 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
Vishnu Nair958da932020-08-21 17:12:37 -07007381 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007382
7383 // Focus events should precede the key events
7384 mUnfocusedWindow->consumeFocusEvent(true);
7385 mFocusedWindow->consumeFocusEvent(false);
7386
7387 // Finish the tap events, which should unblock dispatcher
7388 mUnfocusedWindow->finishEvent(*downSequenceNum);
7389 mUnfocusedWindow->finishEvent(*upSequenceNum);
7390
7391 // Now that all queues are cleared and no backlog in the connections, the key event
7392 // can finally go to the newly focused "mUnfocusedWindow".
7393 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7394 mFocusedWindow->assertNoEvents();
7395 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007396 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007397}
7398
7399// When the touch stream is split across 2 windows, and one of them does not respond,
7400// then ANR should be raised and the touch should be canceled for the unresponsive window.
7401// The other window should not be affected by that.
7402TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
7403 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00007404 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7405 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7406 {FOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007407 mUnfocusedWindow->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_OUTSIDE,
Harry Cutts33476232023-01-30 19:57:29 +00007408 ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007409
7410 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00007411 mDispatcher->notifyMotion(
7412 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7413 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007414
7415 const std::chrono::duration timeout =
7416 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08007417 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007418
7419 mUnfocusedWindow->consumeMotionDown();
7420 mFocusedWindow->consumeMotionDown();
7421 // Focused window may or may not receive ACTION_MOVE
7422 // But it should definitely receive ACTION_CANCEL due to the ANR
7423 InputEvent* event;
7424 std::optional<int32_t> moveOrCancelSequenceNum = mFocusedWindow->receiveEvent(&event);
7425 ASSERT_TRUE(moveOrCancelSequenceNum);
7426 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
7427 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07007428 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007429 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
7430 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
7431 mFocusedWindow->consumeMotionCancel();
7432 } else {
7433 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
7434 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007435 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08007436 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
7437 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007438
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007439 mUnfocusedWindow->assertNoEvents();
7440 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05007441 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07007442}
7443
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007444/**
7445 * If we have no focused window, and a key comes in, we start the ANR timer.
7446 * The focused application should add a focused window before the timer runs out to prevent ANR.
7447 *
7448 * If the user touches another application during this time, the key should be dropped.
7449 * Next, if a new focused window comes in, without toggling the focused application,
7450 * then no ANR should occur.
7451 *
7452 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
7453 * but in some cases the policy may not update the focused application.
7454 */
7455TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
7456 std::shared_ptr<FakeApplicationHandle> focusedApplication =
7457 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007458 focusedApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007459 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
7460 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
7461 mFocusedWindow->setFocusable(false);
7462
7463 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7464 mFocusedWindow->consumeFocusEvent(false);
7465
7466 // Send a key. The ANR timer should start because there is no focused window.
7467 // 'focusedApplication' will get blamed if this timer completes.
7468 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007469 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00007470 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007471 InputEventInjectionSync::NONE, /*injectionTimeout=*/50ms,
Harry Cutts33476232023-01-30 19:57:29 +00007472 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007473 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007474
7475 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
7476 // then the injected touches won't cause the focused event to get dropped.
7477 // The dispatcher only checks for whether the queue should be pruned upon queueing.
7478 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
7479 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
7480 // For this test, it means that the key would get delivered to the window once it becomes
7481 // focused.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07007482 std::this_thread::sleep_for(50ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007483
7484 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007485 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7486 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7487 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05007488
7489 // We do not consume the motion right away, because that would require dispatcher to first
7490 // process (== drop) the key event, and by that time, ANR will be raised.
7491 // Set the focused window first.
7492 mFocusedWindow->setFocusable(true);
7493 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mFocusedWindow, mUnfocusedWindow}}});
7494 setFocusedWindow(mFocusedWindow);
7495 mFocusedWindow->consumeFocusEvent(true);
7496 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
7497 // to another application. This could be a bug / behaviour in the policy.
7498
7499 mUnfocusedWindow->consumeMotionDown();
7500
7501 ASSERT_TRUE(mDispatcher->waitForIdle());
7502 // Should not ANR because we actually have a focused window. It was just added too slowly.
7503 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
7504}
7505
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007506// These tests ensure we cannot send touch events to a window that's positioned behind a window
7507// that has feature NO_INPUT_CHANNEL.
7508// Layout:
7509// Top (closest to user)
7510// mNoInputWindow (above all windows)
7511// mBottomWindow
7512// Bottom (furthest from user)
7513class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
7514 virtual void SetUp() override {
7515 InputDispatcherTest::SetUp();
7516
7517 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007518 mNoInputWindow =
7519 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7520 "Window without input channel", ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007521 /*token=*/std::make_optional<sp<IBinder>>(nullptr));
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007522 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007523 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7524 // It's perfectly valid for this window to not have an associated input channel
7525
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007526 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
7527 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007528 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
7529
7530 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7531 }
7532
7533protected:
7534 std::shared_ptr<FakeApplicationHandle> mApplication;
7535 sp<FakeWindowHandle> mNoInputWindow;
7536 sp<FakeWindowHandle> mBottomWindow;
7537};
7538
7539TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
7540 PointF touchedPoint = {10, 10};
7541
Prabir Pradhan678438e2023-04-13 19:32:51 +00007542 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7543 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7544 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007545
7546 mNoInputWindow->assertNoEvents();
7547 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
7548 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
7549 // and therefore should prevent mBottomWindow from receiving touches
7550 mBottomWindow->assertNoEvents();
7551}
7552
7553/**
7554 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
7555 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
7556 */
7557TEST_F(InputDispatcherMultiWindowOcclusionTests,
7558 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007559 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
7560 "Window with input channel and NO_INPUT_CHANNEL",
7561 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007562
Prabir Pradhan51e7db02022-02-07 06:02:57 -08007563 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007564 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
7565 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mNoInputWindow, mBottomWindow}}});
7566
7567 PointF touchedPoint = {10, 10};
7568
Prabir Pradhan678438e2023-04-13 19:32:51 +00007569 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7570 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7571 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05007572
7573 mNoInputWindow->assertNoEvents();
7574 mBottomWindow->assertNoEvents();
7575}
7576
Vishnu Nair958da932020-08-21 17:12:37 -07007577class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
7578protected:
7579 std::shared_ptr<FakeApplicationHandle> mApp;
7580 sp<FakeWindowHandle> mWindow;
7581 sp<FakeWindowHandle> mMirror;
7582
7583 virtual void SetUp() override {
7584 InputDispatcherTest::SetUp();
7585 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007586 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
7587 mMirror = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindowMirror",
7588 ADISPLAY_ID_DEFAULT, mWindow->getToken());
Vishnu Nair958da932020-08-21 17:12:37 -07007589 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7590 mWindow->setFocusable(true);
7591 mMirror->setFocusable(true);
7592 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7593 }
7594};
7595
7596TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
7597 // Request focus on a mirrored window
7598 setFocusedWindow(mMirror);
7599
7600 // window gets focused
7601 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7603 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007604 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
7605}
7606
7607// A focused & mirrored window remains focused only if the window and its mirror are both
7608// focusable.
7609TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
7610 setFocusedWindow(mMirror);
7611
7612 // window gets focused
7613 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007616 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7618 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007619 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7620
7621 mMirror->setFocusable(false);
7622 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7623
7624 // window loses focus since one of the windows associated with the token in not focusable
7625 mWindow->consumeFocusEvent(false);
7626
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007627 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7628 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007629 mWindow->assertNoEvents();
7630}
7631
7632// A focused & mirrored window remains focused until the window and its mirror both become
7633// invisible.
7634TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
7635 setFocusedWindow(mMirror);
7636
7637 // window gets focused
7638 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7640 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007641 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7643 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007644 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7645
7646 mMirror->setVisible(false);
7647 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7648
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7650 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007651 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7653 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007654 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7655
7656 mWindow->setVisible(false);
7657 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7658
7659 // window loses focus only after all windows associated with the token become invisible.
7660 mWindow->consumeFocusEvent(false);
7661
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007662 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7663 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007664 mWindow->assertNoEvents();
7665}
7666
7667// A focused & mirrored window remains focused until both windows are removed.
7668TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
7669 setFocusedWindow(mMirror);
7670
7671 // window gets focused
7672 mWindow->consumeFocusEvent(true);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7674 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007675 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7677 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007678 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7679
7680 // single window is removed but the window token remains focused
7681 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mMirror}}});
7682
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
7684 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007685 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
7687 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007688 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
7689
7690 // Both windows are removed
7691 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {}}});
7692 mWindow->consumeFocusEvent(false);
7693
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007694 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(mDispatcher))
7695 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07007696 mWindow->assertNoEvents();
7697}
7698
7699// Focus request can be pending until one window becomes visible.
7700TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
7701 // Request focus on an invisible mirror.
7702 mWindow->setVisible(false);
7703 mMirror->setVisible(false);
7704 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7705 setFocusedWindow(mMirror);
7706
7707 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007709 injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
7710 InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007711
7712 mMirror->setVisible(true);
7713 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mMirror}}});
7714
7715 // window gets focused
7716 mWindow->consumeFocusEvent(true);
7717 // window gets the pending key event
7718 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7719}
Prabir Pradhan99987712020-11-10 18:43:05 -08007720
7721class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
7722protected:
7723 std::shared_ptr<FakeApplicationHandle> mApp;
7724 sp<FakeWindowHandle> mWindow;
7725 sp<FakeWindowHandle> mSecondWindow;
7726
7727 void SetUp() override {
7728 InputDispatcherTest::SetUp();
7729 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007730 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007731 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007732 mSecondWindow =
7733 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08007734 mSecondWindow->setFocusable(true);
7735
7736 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
7737 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
7738
7739 setFocusedWindow(mWindow);
7740 mWindow->consumeFocusEvent(true);
7741 }
7742
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007743 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007744 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08007745 }
7746
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007747 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
7748 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08007749 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007750 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
7751 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007752 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007753 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08007754 }
7755};
7756
7757TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
7758 // Ensure that capture cannot be obtained for unfocused windows.
7759 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
7760 mFakePolicy->assertSetPointerCaptureNotCalled();
7761 mSecondWindow->assertNoEvents();
7762
7763 // Ensure that capture can be enabled from the focus window.
7764 requestAndVerifyPointerCapture(mWindow, true);
7765
7766 // Ensure that capture cannot be disabled from a window that does not have capture.
7767 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
7768 mFakePolicy->assertSetPointerCaptureNotCalled();
7769
7770 // Ensure that capture can be disabled from the window with capture.
7771 requestAndVerifyPointerCapture(mWindow, false);
7772}
7773
7774TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007775 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007776
7777 setFocusedWindow(mSecondWindow);
7778
7779 // Ensure that the capture disabled event was sent first.
7780 mWindow->consumeCaptureEvent(false);
7781 mWindow->consumeFocusEvent(false);
7782 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007783 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007784
7785 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007786 notifyPointerCaptureChanged({});
7787 notifyPointerCaptureChanged(request);
7788 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08007789 mWindow->assertNoEvents();
7790 mSecondWindow->assertNoEvents();
7791 mFakePolicy->assertSetPointerCaptureNotCalled();
7792}
7793
7794TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007795 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08007796
7797 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007798 notifyPointerCaptureChanged({});
7799 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08007800
7801 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007802 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08007803 mWindow->consumeCaptureEvent(false);
7804 mWindow->assertNoEvents();
7805}
7806
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007807TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
7808 requestAndVerifyPointerCapture(mWindow, true);
7809
7810 // The first window loses focus.
7811 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007812 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007813 mWindow->consumeCaptureEvent(false);
7814
7815 // Request Pointer Capture from the second window before the notification from InputReader
7816 // arrives.
7817 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007818 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007819
7820 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007821 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007822
7823 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007824 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08007825
7826 mSecondWindow->consumeFocusEvent(true);
7827 mSecondWindow->consumeCaptureEvent(true);
7828}
7829
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00007830TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
7831 // App repeatedly enables and disables capture.
7832 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7833 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7834 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7835 mFakePolicy->assertSetPointerCaptureCalled(false);
7836 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7837 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7838
7839 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
7840 // first request is now stale, this should do nothing.
7841 notifyPointerCaptureChanged(firstRequest);
7842 mWindow->assertNoEvents();
7843
7844 // InputReader notifies that the second request was enabled.
7845 notifyPointerCaptureChanged(secondRequest);
7846 mWindow->consumeCaptureEvent(true);
7847}
7848
Prabir Pradhan7092e262022-05-03 16:51:09 +00007849TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
7850 requestAndVerifyPointerCapture(mWindow, true);
7851
7852 // App toggles pointer capture off and on.
7853 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
7854 mFakePolicy->assertSetPointerCaptureCalled(false);
7855
7856 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
7857 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
7858
7859 // InputReader notifies that the latest "enable" request was processed, while skipping over the
7860 // preceding "disable" request.
7861 notifyPointerCaptureChanged(enableRequest);
7862
7863 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
7864 // any notifications.
7865 mWindow->assertNoEvents();
7866}
7867
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007868class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
7869protected:
7870 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00007871
7872 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
7873 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
7874
7875 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
7876 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7877
7878 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
7879 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
7880 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
7881 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
7882 MAXIMUM_OBSCURING_OPACITY);
7883
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007884 static constexpr gui::Uid TOUCHED_APP_UID{10001};
7885 static constexpr gui::Uid APP_B_UID{10002};
7886 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007887
7888 sp<FakeWindowHandle> mTouchWindow;
7889
7890 virtual void SetUp() override {
7891 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007892 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007893 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
7894 }
7895
7896 virtual void TearDown() override {
7897 InputDispatcherTest::TearDown();
7898 mTouchWindow.clear();
7899 }
7900
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007901 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05007902 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007903 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007904 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007905 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007906 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007907 return window;
7908 }
7909
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007910 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007911 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
7912 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007913 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007914 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007915 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007916 return window;
7917 }
7918
7919 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007920 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
7921 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7922 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007923 }
7924};
7925
7926TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007927 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007928 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007929 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007930
7931 touch();
7932
7933 mTouchWindow->assertNoEvents();
7934}
7935
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007936TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00007937 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
7938 const sp<FakeWindowHandle>& w =
7939 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
7940 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7941
7942 touch();
7943
7944 mTouchWindow->assertNoEvents();
7945}
7946
7947TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007948 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
7949 const sp<FakeWindowHandle>& w =
7950 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
7951 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7952
7953 touch();
7954
7955 w->assertNoEvents();
7956}
7957
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007958TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007959 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
7960 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007961
7962 touch();
7963
7964 mTouchWindow->consumeAnyMotionDown();
7965}
7966
7967TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007968 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007969 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007970 w->setFrame(Rect(0, 0, 50, 50));
7971 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007972
7973 touch({PointF{100, 100}});
7974
7975 mTouchWindow->consumeAnyMotionDown();
7976}
7977
7978TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007979 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00007980 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00007981 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
7982
7983 touch();
7984
7985 mTouchWindow->consumeAnyMotionDown();
7986}
7987
7988TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
7989 const sp<FakeWindowHandle>& w =
7990 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
7991 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00007992
7993 touch();
7994
7995 mTouchWindow->consumeAnyMotionDown();
7996}
7997
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00007998TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
7999 const sp<FakeWindowHandle>& w =
8000 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
8001 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8002
8003 touch();
8004
8005 w->assertNoEvents();
8006}
8007
8008/**
8009 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
8010 * inside) while letting them pass-through. Note that even though touch passes through the occluding
8011 * window, the occluding window will still receive ACTION_OUTSIDE event.
8012 */
8013TEST_F(InputDispatcherUntrustedTouchesTest,
8014 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
8015 const sp<FakeWindowHandle>& w =
8016 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008017 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008018 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8019
8020 touch();
8021
8022 w->consumeMotionOutside();
8023}
8024
8025TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
8026 const sp<FakeWindowHandle>& w =
8027 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008028 w->setWatchOutsideTouch(true);
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008029 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8030
8031 touch();
8032
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08008033 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00008034}
8035
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008036TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008037 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008038 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8039 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008040 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8041
8042 touch();
8043
8044 mTouchWindow->consumeAnyMotionDown();
8045}
8046
8047TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
8048 const sp<FakeWindowHandle>& w =
8049 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8050 MAXIMUM_OBSCURING_OPACITY);
8051 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008052
8053 touch();
8054
8055 mTouchWindow->consumeAnyMotionDown();
8056}
8057
8058TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008059 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008060 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8061 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008062 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8063
8064 touch();
8065
8066 mTouchWindow->assertNoEvents();
8067}
8068
8069TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
8070 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
8071 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008072 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8073 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008074 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008075 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8076 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008077 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8078
8079 touch();
8080
8081 mTouchWindow->assertNoEvents();
8082}
8083
8084TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
8085 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
8086 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008087 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
8088 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008089 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008090 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
8091 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008092 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8093
8094 touch();
8095
8096 mTouchWindow->consumeAnyMotionDown();
8097}
8098
8099TEST_F(InputDispatcherUntrustedTouchesTest,
8100 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
8101 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008102 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8103 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008104 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008105 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8106 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008107 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8108
8109 touch();
8110
8111 mTouchWindow->consumeAnyMotionDown();
8112}
8113
8114TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
8115 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008116 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8117 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008118 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008119 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8120 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00008121 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00008122
8123 touch();
8124
8125 mTouchWindow->assertNoEvents();
8126}
8127
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008128TEST_F(InputDispatcherUntrustedTouchesTest,
8129 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
8130 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008131 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8132 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008133 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008134 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8135 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008136 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8137
8138 touch();
8139
8140 mTouchWindow->assertNoEvents();
8141}
8142
8143TEST_F(InputDispatcherUntrustedTouchesTest,
8144 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
8145 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008146 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8147 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008148 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008149 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8150 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008151 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wA, wB, mTouchWindow}}});
8152
8153 touch();
8154
8155 mTouchWindow->consumeAnyMotionDown();
8156}
8157
8158TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
8159 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008160 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
8161 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00008162 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8163
8164 touch();
8165
8166 mTouchWindow->consumeAnyMotionDown();
8167}
8168
8169TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
8170 const sp<FakeWindowHandle>& w =
8171 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
8172 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8173
8174 touch();
8175
8176 mTouchWindow->consumeAnyMotionDown();
8177}
8178
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008179TEST_F(InputDispatcherUntrustedTouchesTest,
8180 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
8181 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8182 const sp<FakeWindowHandle>& w =
8183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
8184 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8185
8186 touch();
8187
8188 mTouchWindow->assertNoEvents();
8189}
8190
8191TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
8192 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
8193 const sp<FakeWindowHandle>& w =
8194 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
8195 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8196
8197 touch();
8198
8199 mTouchWindow->consumeAnyMotionDown();
8200}
8201
8202TEST_F(InputDispatcherUntrustedTouchesTest,
8203 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
8204 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
8205 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00008206 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8207 OPACITY_ABOVE_THRESHOLD);
8208 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8209
8210 touch();
8211
8212 mTouchWindow->consumeAnyMotionDown();
8213}
8214
8215TEST_F(InputDispatcherUntrustedTouchesTest,
8216 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
8217 const sp<FakeWindowHandle>& w1 =
8218 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8219 OPACITY_BELOW_THRESHOLD);
8220 const sp<FakeWindowHandle>& w2 =
8221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
8222 OPACITY_BELOW_THRESHOLD);
8223 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
8224
8225 touch();
8226
8227 mTouchWindow->assertNoEvents();
8228}
8229
8230/**
8231 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
8232 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
8233 * (which alone would result in allowing touches) does not affect the blocking behavior.
8234 */
8235TEST_F(InputDispatcherUntrustedTouchesTest,
8236 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
8237 const sp<FakeWindowHandle>& wB =
8238 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
8239 OPACITY_BELOW_THRESHOLD);
8240 const sp<FakeWindowHandle>& wC =
8241 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
8242 OPACITY_BELOW_THRESHOLD);
8243 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
8244
8245 touch();
8246
8247 mTouchWindow->assertNoEvents();
8248}
8249
8250/**
8251 * This test is testing that a window from a different UID but with same application token doesn't
8252 * block the touch. Apps can share the application token for close UI collaboration for example.
8253 */
8254TEST_F(InputDispatcherUntrustedTouchesTest,
8255 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
8256 const sp<FakeWindowHandle>& w =
8257 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
8258 w->setApplicationToken(mTouchWindow->getApplicationToken());
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00008259 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
8260
8261 touch();
8262
8263 mTouchWindow->consumeAnyMotionDown();
8264}
8265
arthurhungb89ccb02020-12-30 16:19:01 +08008266class InputDispatcherDragTests : public InputDispatcherTest {
8267protected:
8268 std::shared_ptr<FakeApplicationHandle> mApp;
8269 sp<FakeWindowHandle> mWindow;
8270 sp<FakeWindowHandle> mSecondWindow;
8271 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008272 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008273 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
8274 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +08008275
8276 void SetUp() override {
8277 InputDispatcherTest::SetUp();
8278 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008279 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008280 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008281
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008282 mSecondWindow =
8283 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +08008284 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +08008285
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008286 mSpyWindow =
8287 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008288 mSpyWindow->setSpy(true);
8289 mSpyWindow->setTrustedOverlay(true);
8290 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
8291
arthurhungb89ccb02020-12-30 16:19:01 +08008292 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008293 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008294 }
8295
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008296 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
8297 switch (fromSource) {
8298 case AINPUT_SOURCE_TOUCHSCREEN:
8299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8300 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8301 ADISPLAY_ID_DEFAULT, {50, 50}))
8302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8303 break;
8304 case AINPUT_SOURCE_STYLUS:
8305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8306 injectMotionEvent(
8307 mDispatcher,
8308 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8309 AINPUT_SOURCE_STYLUS)
8310 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008311 .pointer(PointerBuilder(0, ToolType::STYLUS)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008312 .x(50)
8313 .y(50))
8314 .build()));
8315 break;
8316 case AINPUT_SOURCE_MOUSE:
8317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8318 injectMotionEvent(
8319 mDispatcher,
8320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8321 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8322 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008323 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008324 .x(50)
8325 .y(50))
8326 .build()));
8327 break;
8328 default:
8329 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
8330 }
arthurhungb89ccb02020-12-30 16:19:01 +08008331
8332 // Window should receive motion event.
8333 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008334 // Spy window should also receive motion event
8335 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +00008336 }
8337
8338 // Start performing drag, we will create a drag window and transfer touch to it.
8339 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
8340 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008341 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +00008342 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008343 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +00008344 }
arthurhungb89ccb02020-12-30 16:19:01 +08008345
8346 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008347 mDragWindow =
8348 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008349 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
arthurhungb89ccb02020-12-30 16:19:01 +08008350 mDispatcher->setInputWindows(
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008351 {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
arthurhungb89ccb02020-12-30 16:19:01 +08008352
8353 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +00008354 bool transferred =
8355 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +00008356 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +00008357 if (transferred) {
8358 mWindow->consumeMotionCancel();
8359 mDragWindow->consumeMotionDown();
8360 }
8361 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +08008362 }
8363};
8364
8365TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008366 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +08008367
8368 // Move on window.
8369 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8370 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8371 ADISPLAY_ID_DEFAULT, {50, 50}))
8372 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8373 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8374 mWindow->consumeDragEvent(false, 50, 50);
8375 mSecondWindow->assertNoEvents();
8376
8377 // Move to another window.
8378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8379 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8380 ADISPLAY_ID_DEFAULT, {150, 50}))
8381 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8382 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8383 mWindow->consumeDragEvent(true, 150, 50);
8384 mSecondWindow->consumeDragEvent(false, 50, 50);
8385
8386 // Move back to original window.
8387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8388 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8389 ADISPLAY_ID_DEFAULT, {50, 50}))
8390 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8391 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8392 mWindow->consumeDragEvent(false, 50, 50);
8393 mSecondWindow->consumeDragEvent(true, -50, 50);
8394
8395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8396 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {50, 50}))
8397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8398 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8399 mWindow->assertNoEvents();
8400 mSecondWindow->assertNoEvents();
8401}
8402
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008403TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008404 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008405
8406 // No cancel event after drag start
8407 mSpyWindow->assertNoEvents();
8408
8409 const MotionEvent secondFingerDownEvent =
8410 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8411 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008412 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8413 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +00008414 .build();
8415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8416 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8417 InputEventInjectionSync::WAIT_FOR_RESULT))
8418 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8419
8420 // Receives cancel for first pointer after next pointer down
8421 mSpyWindow->consumeMotionCancel();
8422 mSpyWindow->consumeMotionDown();
8423
8424 mSpyWindow->assertNoEvents();
8425}
8426
arthurhungf452d0b2021-01-06 00:19:52 +08008427TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008428 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +08008429
8430 // Move on window.
8431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8432 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8433 ADISPLAY_ID_DEFAULT, {50, 50}))
8434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8435 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8436 mWindow->consumeDragEvent(false, 50, 50);
8437 mSecondWindow->assertNoEvents();
8438
8439 // Move to another window.
8440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8441 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8442 ADISPLAY_ID_DEFAULT, {150, 50}))
8443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8444 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8445 mWindow->consumeDragEvent(true, 150, 50);
8446 mSecondWindow->consumeDragEvent(false, 50, 50);
8447
8448 // drop to another window.
8449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8450 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8451 {150, 50}))
8452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8453 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008454 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +08008455 mWindow->assertNoEvents();
8456 mSecondWindow->assertNoEvents();
8457}
8458
arthurhung6d4bed92021-03-17 11:59:33 +08008459TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008460 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +08008461
8462 // Move on window and keep button pressed.
8463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8464 injectMotionEvent(mDispatcher,
8465 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8466 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008467 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008468 .build()))
8469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8470 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8471 mWindow->consumeDragEvent(false, 50, 50);
8472 mSecondWindow->assertNoEvents();
8473
8474 // Move to another window and release button, expect to drop item.
8475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8476 injectMotionEvent(mDispatcher,
8477 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
8478 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008479 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008480 .build()))
8481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8482 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8483 mWindow->assertNoEvents();
8484 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008485 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +08008486
8487 // nothing to the window.
8488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8489 injectMotionEvent(mDispatcher,
8490 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
8491 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008492 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +08008493 .build()))
8494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8495 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
8496 mWindow->assertNoEvents();
8497 mSecondWindow->assertNoEvents();
8498}
8499
Arthur Hung54745652022-04-20 07:17:41 +00008500TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008501 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +08008502
8503 // Set second window invisible.
8504 mSecondWindow->setVisible(false);
8505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
8506
8507 // Move on window.
8508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8509 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8510 ADISPLAY_ID_DEFAULT, {50, 50}))
8511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8512 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8513 mWindow->consumeDragEvent(false, 50, 50);
8514 mSecondWindow->assertNoEvents();
8515
8516 // Move to another window.
8517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8518 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8519 ADISPLAY_ID_DEFAULT, {150, 50}))
8520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8521 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8522 mWindow->consumeDragEvent(true, 150, 50);
8523 mSecondWindow->assertNoEvents();
8524
8525 // drop to another window.
8526 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8527 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8528 {150, 50}))
8529 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8530 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008531 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +08008532 mWindow->assertNoEvents();
8533 mSecondWindow->assertNoEvents();
8534}
8535
Arthur Hung54745652022-04-20 07:17:41 +00008536TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008537 // Ensure window could track pointerIds if it didn't support split touch.
8538 mWindow->setPreventSplitting(true);
8539
Arthur Hung54745652022-04-20 07:17:41 +00008540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8541 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8542 {50, 50}))
8543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8544 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8545
8546 const MotionEvent secondFingerDownEvent =
8547 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8548 .displayId(ADISPLAY_ID_DEFAULT)
8549 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008550 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
8551 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008552 .build();
8553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8554 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8555 InputEventInjectionSync::WAIT_FOR_RESULT))
8556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00008557 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +00008558
8559 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008560 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008561}
8562
8563TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
8564 // First down on second window.
8565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8566 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8567 {150, 50}))
8568 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8569
8570 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8571
8572 // Second down on first window.
8573 const MotionEvent secondFingerDownEvent =
8574 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8575 .displayId(ADISPLAY_ID_DEFAULT)
8576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008579 .build();
8580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8581 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
8582 InputEventInjectionSync::WAIT_FOR_RESULT))
8583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8584 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8585
8586 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008587 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +00008588
8589 // Move on window.
8590 const MotionEvent secondFingerMoveEvent =
8591 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8592 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008593 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8594 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008595 .build();
8596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8597 injectMotionEvent(mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
8598 InputEventInjectionSync::WAIT_FOR_RESULT));
8599 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8600 mWindow->consumeDragEvent(false, 50, 50);
8601 mSecondWindow->consumeMotionMove();
8602
8603 // Release the drag pointer should perform drop.
8604 const MotionEvent secondFingerUpEvent =
8605 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8606 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008607 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
8608 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +00008609 .build();
8610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8611 injectMotionEvent(mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
8612 InputEventInjectionSync::WAIT_FOR_RESULT));
8613 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008614 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +00008615 mWindow->assertNoEvents();
8616 mSecondWindow->consumeMotionMove();
8617}
8618
Arthur Hung3915c1f2022-05-31 07:17:17 +00008619TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008620 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +00008621
8622 // Update window of second display.
8623 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008624 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008625 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8626
8627 // Let second display has a touch state.
8628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8629 injectMotionEvent(mDispatcher,
8630 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8631 AINPUT_SOURCE_TOUCHSCREEN)
8632 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008633 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +00008634 .build()));
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07008635 windowInSecondary->consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
Harry Cutts33476232023-01-30 19:57:29 +00008636 SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +00008637 // Update window again.
8638 mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}});
8639
8640 // Move on window.
8641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8642 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8643 ADISPLAY_ID_DEFAULT, {50, 50}))
8644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8645 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8646 mWindow->consumeDragEvent(false, 50, 50);
8647 mSecondWindow->assertNoEvents();
8648
8649 // Move to another window.
8650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8651 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8652 ADISPLAY_ID_DEFAULT, {150, 50}))
8653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8654 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8655 mWindow->consumeDragEvent(true, 150, 50);
8656 mSecondWindow->consumeDragEvent(false, 50, 50);
8657
8658 // drop to another window.
8659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8660 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8661 {150, 50}))
8662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8663 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008664 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +00008665 mWindow->assertNoEvents();
8666 mSecondWindow->assertNoEvents();
8667}
8668
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008669TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
8670 startDrag(true, AINPUT_SOURCE_MOUSE);
8671 // Move on window.
8672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8673 injectMotionEvent(mDispatcher,
8674 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8675 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8676 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008677 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008678 .x(50)
8679 .y(50))
8680 .build()))
8681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8682 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8683 mWindow->consumeDragEvent(false, 50, 50);
8684 mSecondWindow->assertNoEvents();
8685
8686 // Move to another window.
8687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8688 injectMotionEvent(mDispatcher,
8689 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
8690 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
8691 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008692 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008693 .x(150)
8694 .y(50))
8695 .build()))
8696 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8697 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
8698 mWindow->consumeDragEvent(true, 150, 50);
8699 mSecondWindow->consumeDragEvent(false, 50, 50);
8700
8701 // drop to another window.
8702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8703 injectMotionEvent(mDispatcher,
8704 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
8705 .buttonState(0)
8706 .pointer(PointerBuilder(MOUSE_POINTER_ID,
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008707 ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008708 .x(150)
8709 .y(50))
8710 .build()))
8711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8712 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -07008713 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +00008714 mWindow->assertNoEvents();
8715 mSecondWindow->assertNoEvents();
8716}
8717
Vishnu Nair062a8672021-09-03 16:07:44 -07008718class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
8719
8720TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
8721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8723 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008724 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008725 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8726 window->setFocusable(true);
8727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8728 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008729 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008730
8731 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008732 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008733 window->assertNoEvents();
8734
Prabir Pradhan678438e2023-04-13 19:32:51 +00008735 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8736 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008737 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8738 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008739 window->assertNoEvents();
8740
8741 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008742 window->setDropInput(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008743 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
8744
Prabir Pradhan678438e2023-04-13 19:32:51 +00008745 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008746 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8747
Prabir Pradhan678438e2023-04-13 19:32:51 +00008748 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8749 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008750 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8751 window->assertNoEvents();
8752}
8753
8754TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
8755 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8756 std::make_shared<FakeApplicationHandle>();
8757 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008758 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8759 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008760 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008761 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008762 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008763 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008764 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8765 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008766 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008767 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008768 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8769 window->setFocusable(true);
8770 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8771 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008772 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008773
8774 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008775 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008776 window->assertNoEvents();
8777
Prabir Pradhan678438e2023-04-13 19:32:51 +00008778 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8779 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008780 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8781 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008782 window->assertNoEvents();
8783
8784 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008785 window->setDropInputIfObscured(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008786 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8787
Prabir Pradhan678438e2023-04-13 19:32:51 +00008788 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008789 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8790
Prabir Pradhan678438e2023-04-13 19:32:51 +00008791 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8792 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008793 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8794 window->assertNoEvents();
8795}
8796
8797TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
8798 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
8799 std::make_shared<FakeApplicationHandle>();
8800 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008801 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
8802 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -07008803 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008804 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008805 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -07008806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008807 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
8808 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008809 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008810 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -07008811 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8812 window->setFocusable(true);
8813 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {obscuringWindow, window}}});
8814 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008815 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -07008816
8817 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +00008818 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008819 window->assertNoEvents();
8820
Prabir Pradhan678438e2023-04-13 19:32:51 +00008821 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8822 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -07008823 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
8824 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008825 window->assertNoEvents();
8826
8827 // When the window is no longer obscured because it went on top, it should get input
8828 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, obscuringWindow}}});
8829
Prabir Pradhan678438e2023-04-13 19:32:51 +00008830 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008831 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
8832
Prabir Pradhan678438e2023-04-13 19:32:51 +00008833 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8834 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -07008835 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8836 window->assertNoEvents();
8837}
8838
Antonio Kantekf16f2832021-09-28 04:39:20 +00008839class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
8840protected:
8841 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +00008842 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008843 sp<FakeWindowHandle> mWindow;
8844 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +00008845 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +00008846
8847 void SetUp() override {
8848 InputDispatcherTest::SetUp();
8849
8850 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +00008851 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008852 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008853 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008854 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008855 mSecondWindow =
8856 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008857 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +00008858 mThirdWindow =
8859 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
8860 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
8861 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008862
8863 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Antonio Kantek15beb512022-06-13 22:35:41 +00008864 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}},
8865 {SECOND_DISPLAY_ID, {mThirdWindow}}});
8866 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008867 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008868
Antonio Kantek15beb512022-06-13 22:35:41 +00008869 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +00008870 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008871 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -07008872 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
8873 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008874 mThirdWindow->assertNoEvents();
8875 }
8876
8877 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
8878 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +00008879 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +00008880 SECOND_DISPLAY_ID)) {
8881 mWindow->assertNoEvents();
8882 mSecondWindow->assertNoEvents();
8883 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -07008884 }
Antonio Kantekf16f2832021-09-28 04:39:20 +00008885 }
8886
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008887 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +00008888 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -07008889 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
8890 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008891 mWindow->consumeTouchModeEvent(inTouchMode);
8892 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +00008893 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +00008894 }
8895};
8896
Antonio Kantek26defcf2022-02-08 01:12:27 +00008897TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008898 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +00008899 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
8900 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008901 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008902}
8903
Antonio Kantek26defcf2022-02-08 01:12:27 +00008904TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
8905 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008906 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008907 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008908 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008909 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008910 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -07008911 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +00008912 mWindow->assertNoEvents();
8913 mSecondWindow->assertNoEvents();
8914}
8915
8916TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
8917 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008918 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008919 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008920 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +00008921 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +00008922 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +00008923}
8924
Antonio Kantekf16f2832021-09-28 04:39:20 +00008925TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -08008926 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +00008927 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
8928 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008929 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +00008930 mWindow->assertNoEvents();
8931 mSecondWindow->assertNoEvents();
8932}
8933
Antonio Kantek15beb512022-06-13 22:35:41 +00008934TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
8935 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
8936 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8937 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008938 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +00008939 mWindow->assertNoEvents();
8940 mSecondWindow->assertNoEvents();
8941 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
8942}
8943
Antonio Kantek48710e42022-03-24 14:19:30 -07008944TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
8945 // Interact with the window first.
8946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher, ADISPLAY_ID_DEFAULT))
8947 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8948 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8949
8950 // Then remove focus.
8951 mWindow->setFocusable(false);
8952 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
8953
8954 // Assert that caller can switch touch mode by owning one of the last interacted window.
8955 const WindowInfo& windowInfo = *mWindow->getInfo();
8956 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
8957 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00008958 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -07008959}
8960
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008961class InputDispatcherSpyWindowTest : public InputDispatcherTest {
8962public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008963 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008964 std::shared_ptr<FakeApplicationHandle> application =
8965 std::make_shared<FakeApplicationHandle>();
8966 std::string name = "Fake Spy ";
8967 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008968 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
8969 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008970 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008971 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008972 return spy;
8973 }
8974
8975 sp<FakeWindowHandle> createForeground() {
8976 std::shared_ptr<FakeApplicationHandle> application =
8977 std::make_shared<FakeApplicationHandle>();
8978 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008979 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
8980 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008981 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008982 return window;
8983 }
8984
8985private:
8986 int mSpyCount{0};
8987};
8988
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008989using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -08008990/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008991 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
8992 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008993TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -07008994 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08008995 ScopedSilentDeath _silentDeath;
8996
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008997 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -08008998 spy->setTrustedOverlay(false);
8999 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}}),
9000 ".* not a trusted overlay");
9001}
9002
9003/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009004 * Input injection into a display with a spy window but no foreground windows should succeed.
9005 */
9006TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009007 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009008 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy}}});
9009
9010 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9011 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9012 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9013 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9014}
9015
9016/**
9017 * Verify the order in which different input windows receive events. The touched foreground window
9018 * (if there is one) should always receive the event first. When there are multiple spy windows, the
9019 * spy windows will receive the event according to their Z-order, where the top-most spy window will
9020 * receive events before ones belows it.
9021 *
9022 * Here, we set up a scenario with four windows in the following Z order from the top:
9023 * spy1, spy2, window, spy3.
9024 * We then inject an event and verify that the foreground "window" receives it first, followed by
9025 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
9026 * window.
9027 */
9028TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
9029 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009030 auto spy1 = createSpy();
9031 auto spy2 = createSpy();
9032 auto spy3 = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009033 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window, spy3}}});
9034 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
9035 const size_t numChannels = channels.size();
9036
Michael Wright8e9a8562022-02-09 13:44:29 +00009037 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009038 if (!epollFd.ok()) {
9039 FAIL() << "Failed to create epoll fd";
9040 }
9041
9042 for (size_t i = 0; i < numChannels; i++) {
9043 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
9044 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
9045 FAIL() << "Failed to add fd to epoll";
9046 }
9047 }
9048
9049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9050 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9051 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9052
9053 std::vector<size_t> eventOrder;
9054 std::vector<struct epoll_event> events(numChannels);
9055 for (;;) {
9056 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
9057 (100ms).count());
9058 if (nFds < 0) {
9059 FAIL() << "Failed to call epoll_wait";
9060 }
9061 if (nFds == 0) {
9062 break; // epoll_wait timed out
9063 }
9064 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -07009065 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -07009066 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009067 channels[i]->consumeMotionDown();
9068 }
9069 }
9070
9071 // Verify the order in which the events were received.
9072 EXPECT_EQ(3u, eventOrder.size());
9073 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
9074 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
9075 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
9076}
9077
9078/**
9079 * A spy window using the NOT_TOUCHABLE flag does not receive events.
9080 */
9081TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
9082 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009083 auto spy = createSpy();
9084 spy->setTouchable(false);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009085 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9086
9087 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9088 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9090 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9091 spy->assertNoEvents();
9092}
9093
9094/**
9095 * A spy window will only receive gestures that originate within its touchable region. Gestures that
9096 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
9097 * to the window.
9098 */
9099TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
9100 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009101 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009102 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
9103 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9104
9105 // Inject an event outside the spy window's touchable region.
9106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9107 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9109 window->consumeMotionDown();
9110 spy->assertNoEvents();
9111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9112 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9113 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9114 window->consumeMotionUp();
9115 spy->assertNoEvents();
9116
9117 // Inject an event inside the spy window's touchable region.
9118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9119 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9120 {5, 10}))
9121 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9122 window->consumeMotionDown();
9123 spy->consumeMotionDown();
9124}
9125
9126/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009127 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009128 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009129 */
9130TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
9131 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009132 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009133 auto spy = createSpy();
9134 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009135 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009136 spy->setFrame(Rect{0, 0, 20, 20});
9137 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9138
9139 // Inject an event outside the spy window's frame and touchable region.
9140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009141 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9142 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009143 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9144 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009145 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009146}
9147
9148/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009149 * Even when a spy window spans over multiple foreground windows, the spy should receive all
9150 * pointers that are down within its bounds.
9151 */
9152TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
9153 auto windowLeft = createForeground();
9154 windowLeft->setFrame({0, 0, 100, 200});
9155 auto windowRight = createForeground();
9156 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009157 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009158 spy->setFrame({0, 0, 200, 200});
9159 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, windowLeft, windowRight}}});
9160
9161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9162 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9163 {50, 50}))
9164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9165 windowLeft->consumeMotionDown();
9166 spy->consumeMotionDown();
9167
9168 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009169 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009170 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009171 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9172 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009173 .build();
9174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9175 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9176 InputEventInjectionSync::WAIT_FOR_RESULT))
9177 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9178 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +00009179 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009180}
9181
9182/**
9183 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
9184 * the spy should receive the second pointer with ACTION_DOWN.
9185 */
9186TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
9187 auto window = createForeground();
9188 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009189 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009190 spyRight->setFrame({100, 0, 200, 200});
9191 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyRight, window}}});
9192
9193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9194 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9195 {50, 50}))
9196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9197 window->consumeMotionDown();
9198 spyRight->assertNoEvents();
9199
9200 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009201 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009202 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009203 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
9204 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009205 .build();
9206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9207 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9208 InputEventInjectionSync::WAIT_FOR_RESULT))
9209 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00009210 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -08009211 spyRight->consumeMotionDown();
9212}
9213
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009214/**
9215 * The spy window should not be able to affect whether or not touches are split. Only the foreground
9216 * windows should be allowed to control split touch.
9217 */
9218TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009219 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009220 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009221 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08009222 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009223
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009224 auto window = createForeground();
9225 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009226
9227 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9228
9229 // First finger down, no window touched.
9230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9231 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9232 {100, 200}))
9233 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9234 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9235 window->assertNoEvents();
9236
9237 // Second finger down on window, the window should receive touch down.
9238 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08009239 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009240 .displayId(ADISPLAY_ID_DEFAULT)
9241 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009242 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9243 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009244 .build();
9245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9246 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9247 InputEventInjectionSync::WAIT_FOR_RESULT))
9248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9249
9250 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00009251 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009252}
9253
9254/**
9255 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
9256 * do not receive key events.
9257 */
9258TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009259 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009260 spy->setFocusable(false);
9261
9262 auto window = createForeground();
9263 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9264 setFocusedWindow(window);
9265 window->consumeFocusEvent(true);
9266
9267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher))
9268 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9269 window->consumeKeyDown(ADISPLAY_ID_NONE);
9270
9271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(mDispatcher))
9272 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9273 window->consumeKeyUp(ADISPLAY_ID_NONE);
9274
9275 spy->assertNoEvents();
9276}
9277
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009278using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
9279
9280/**
9281 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
9282 * are currently sent to any other windows - including other spy windows - will also be cancelled.
9283 */
9284TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
9285 auto window = createForeground();
9286 auto spy1 = createSpy();
9287 auto spy2 = createSpy();
9288 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
9289
9290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9291 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9293 window->consumeMotionDown();
9294 spy1->consumeMotionDown();
9295 spy2->consumeMotionDown();
9296
9297 // Pilfer pointers from the second spy window.
9298 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
9299 spy2->assertNoEvents();
9300 spy1->consumeMotionCancel();
9301 window->consumeMotionCancel();
9302
9303 // The rest of the gesture should only be sent to the second spy window.
9304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9305 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
9306 ADISPLAY_ID_DEFAULT))
9307 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9308 spy2->consumeMotionMove();
9309 spy1->assertNoEvents();
9310 window->assertNoEvents();
9311}
9312
9313/**
9314 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
9315 * in the middle of the gesture.
9316 */
9317TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
9318 auto window = createForeground();
9319 auto spy = createSpy();
9320 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9321
9322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9323 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9324 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9325 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9326 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9327
9328 window->releaseChannel();
9329
9330 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9331
9332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9333 injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
9334 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9335 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
9336}
9337
9338/**
9339 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
9340 * the spy, but not to any other windows.
9341 */
9342TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
9343 auto spy = createSpy();
9344 auto window = createForeground();
9345
9346 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9347
9348 // First finger down on the window and the spy.
9349 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9350 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9351 {100, 200}))
9352 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9353 spy->consumeMotionDown();
9354 window->consumeMotionDown();
9355
9356 // Spy window pilfers the pointers.
9357 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9358 window->consumeMotionCancel();
9359
9360 // Second finger down on the window and spy, but the window should not receive the pointer down.
9361 const MotionEvent secondFingerDownEvent =
9362 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9363 .displayId(ADISPLAY_ID_DEFAULT)
9364 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009365 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9366 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009367 .build();
9368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9369 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9370 InputEventInjectionSync::WAIT_FOR_RESULT))
9371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9372
Harry Cutts33476232023-01-30 19:57:29 +00009373 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009374
9375 // Third finger goes down outside all windows, so injection should fail.
9376 const MotionEvent thirdFingerDownEvent =
9377 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9378 .displayId(ADISPLAY_ID_DEFAULT)
9379 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009380 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9381 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
9382 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009383 .build();
9384 ASSERT_EQ(InputEventInjectionResult::FAILED,
9385 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9386 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009387 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009388
9389 spy->assertNoEvents();
9390 window->assertNoEvents();
9391}
9392
9393/**
9394 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
9395 */
9396TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
9397 auto spy = createSpy();
9398 spy->setFrame(Rect(0, 0, 100, 100));
9399 auto window = createForeground();
9400 window->setFrame(Rect(0, 0, 200, 200));
9401
9402 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9403
9404 // First finger down on the window only
9405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9406 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9407 {150, 150}))
9408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9409 window->consumeMotionDown();
9410
9411 // Second finger down on the spy and window
9412 const MotionEvent secondFingerDownEvent =
9413 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9414 .displayId(ADISPLAY_ID_DEFAULT)
9415 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009416 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9417 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009418 .build();
9419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9420 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9421 InputEventInjectionSync::WAIT_FOR_RESULT))
9422 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9423 spy->consumeMotionDown();
9424 window->consumeMotionPointerDown(1);
9425
9426 // Third finger down on the spy and window
9427 const MotionEvent thirdFingerDownEvent =
9428 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9429 .displayId(ADISPLAY_ID_DEFAULT)
9430 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009431 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
9432 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
9433 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009434 .build();
9435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9436 injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
9437 InputEventInjectionSync::WAIT_FOR_RESULT))
9438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9439 spy->consumeMotionPointerDown(1);
9440 window->consumeMotionPointerDown(2);
9441
9442 // Spy window pilfers the pointers.
9443 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +00009444 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
9445 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009446
9447 spy->assertNoEvents();
9448 window->assertNoEvents();
9449}
9450
9451/**
9452 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
9453 * other windows should be canceled. If this results in the cancellation of all pointers for some
9454 * window, then that window should receive ACTION_CANCEL.
9455 */
9456TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
9457 auto spy = createSpy();
9458 spy->setFrame(Rect(0, 0, 100, 100));
9459 auto window = createForeground();
9460 window->setFrame(Rect(0, 0, 200, 200));
9461
9462 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9463
9464 // First finger down on both spy and window
9465 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9466 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9467 {10, 10}))
9468 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9469 window->consumeMotionDown();
9470 spy->consumeMotionDown();
9471
9472 // Second finger down on the spy and window
9473 const MotionEvent secondFingerDownEvent =
9474 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9475 .displayId(ADISPLAY_ID_DEFAULT)
9476 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009477 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9478 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009479 .build();
9480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9481 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9482 InputEventInjectionSync::WAIT_FOR_RESULT))
9483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9484 spy->consumeMotionPointerDown(1);
9485 window->consumeMotionPointerDown(1);
9486
9487 // Spy window pilfers the pointers.
9488 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9489 window->consumeMotionCancel();
9490
9491 spy->assertNoEvents();
9492 window->assertNoEvents();
9493}
9494
9495/**
9496 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
9497 * be sent to other windows
9498 */
9499TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
9500 auto spy = createSpy();
9501 spy->setFrame(Rect(0, 0, 100, 100));
9502 auto window = createForeground();
9503 window->setFrame(Rect(0, 0, 200, 200));
9504
9505 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9506
9507 // First finger down on both window and spy
9508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9509 injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9510 {10, 10}))
9511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9512 window->consumeMotionDown();
9513 spy->consumeMotionDown();
9514
9515 // Spy window pilfers the pointers.
9516 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
9517 window->consumeMotionCancel();
9518
9519 // Second finger down on the window only
9520 const MotionEvent secondFingerDownEvent =
9521 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9522 .displayId(ADISPLAY_ID_DEFAULT)
9523 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009524 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
9525 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +00009526 .build();
9527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9528 injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
9529 InputEventInjectionSync::WAIT_FOR_RESULT))
9530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9531 window->consumeMotionDown();
9532 window->assertNoEvents();
9533
9534 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
9535 spy->consumeMotionMove();
9536 spy->assertNoEvents();
9537}
9538
Prabir Pradhand65552b2021-10-07 11:23:50 -07009539class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
9540public:
9541 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
9542 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9543 std::make_shared<FakeApplicationHandle>();
9544 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009545 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
9546 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009547 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009548 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009549 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009550 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009551 overlay->setTrustedOverlay(true);
9552
9553 std::shared_ptr<FakeApplicationHandle> application =
9554 std::make_shared<FakeApplicationHandle>();
9555 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009556 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
9557 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009558 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009559 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -07009560
9561 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
9562 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9563 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00009564 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009565 return {std::move(overlay), std::move(window)};
9566 }
9567
9568 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009569 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -07009570 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +00009571 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -07009572 }
9573
9574 void sendStylusEvent(int32_t action) {
9575 NotifyMotionArgs motionArgs =
9576 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
9577 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009578 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +00009579 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009580 }
9581};
9582
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009583using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
9584
9585TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -07009586 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -08009587 ScopedSilentDeath _silentDeath;
9588
Prabir Pradhand65552b2021-10-07 11:23:50 -07009589 auto [overlay, window] = setupStylusOverlayScenario();
9590 overlay->setTrustedOverlay(false);
9591 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
9592 ASSERT_DEATH(mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}}),
9593 ".* not a trusted overlay");
9594}
9595
9596TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
9597 auto [overlay, window] = setupStylusOverlayScenario();
9598 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9599
9600 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9601 overlay->consumeMotionDown();
9602 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9603 overlay->consumeMotionUp();
9604
9605 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9606 window->consumeMotionDown();
9607 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9608 window->consumeMotionUp();
9609
9610 overlay->assertNoEvents();
9611 window->assertNoEvents();
9612}
9613
9614TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
9615 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009616 overlay->setSpy(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -07009617 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9618
9619 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9620 overlay->consumeMotionDown();
9621 window->consumeMotionDown();
9622 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9623 overlay->consumeMotionUp();
9624 window->consumeMotionUp();
9625
9626 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
9627 window->consumeMotionDown();
9628 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
9629 window->consumeMotionUp();
9630
9631 overlay->assertNoEvents();
9632 window->assertNoEvents();
9633}
9634
Prabir Pradhan6dfbf262022-03-14 15:24:30 +00009635/**
9636 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
9637 * The scenario is as follows:
9638 * - The stylus interceptor overlay is configured as a spy window.
9639 * - The stylus interceptor spy receives the start of a new stylus gesture.
9640 * - It pilfers pointers and then configures itself to no longer be a spy.
9641 * - The stylus interceptor continues to receive the rest of the gesture.
9642 */
9643TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
9644 auto [overlay, window] = setupStylusOverlayScenario();
9645 overlay->setSpy(true);
9646 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9647
9648 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
9649 overlay->consumeMotionDown();
9650 window->consumeMotionDown();
9651
9652 // The interceptor pilfers the pointers.
9653 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
9654 window->consumeMotionCancel();
9655
9656 // The interceptor configures itself so that it is no longer a spy.
9657 overlay->setSpy(false);
9658 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {overlay, window}}});
9659
9660 // It continues to receive the rest of the stylus gesture.
9661 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
9662 overlay->consumeMotionMove();
9663 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
9664 overlay->consumeMotionUp();
9665
9666 window->assertNoEvents();
9667}
9668
Prabir Pradhan5735a322022-04-11 17:23:34 +00009669struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009670 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009671 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +00009672 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
9673 std::unique_ptr<InputDispatcher>& mDispatcher;
9674
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009675 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +00009676 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
9677
9678 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
9679 return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
9680 ADISPLAY_ID_DEFAULT, {100, 200},
9681 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9682 AMOTION_EVENT_INVALID_CURSOR_POSITION},
9683 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
9684 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
9685 }
9686
9687 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Harry Cutts33476232023-01-30 19:57:29 +00009688 return inputdispatcher::injectKey(mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +00009689 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +00009690 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +00009691 mPolicyFlags);
9692 }
9693
9694 sp<FakeWindowHandle> createWindow() const {
9695 std::shared_ptr<FakeApplicationHandle> overlayApplication =
9696 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009697 sp<FakeWindowHandle> window =
9698 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, "Owned Window",
9699 ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +00009700 window->setOwnerInfo(mPid, mUid);
9701 return window;
9702 }
9703};
9704
9705using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
9706
9707TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009708 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009709 auto window = owner.createWindow();
9710 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9711
9712 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9713 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9714 window->consumeMotionDown();
9715
9716 setFocusedWindow(window);
9717 window->consumeFocusEvent(true);
9718
9719 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9720 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9721 window->consumeKeyDown(ADISPLAY_ID_NONE);
9722}
9723
9724TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009725 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009726 auto window = owner.createWindow();
9727 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
9728
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009729 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009730 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9731 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9732
9733 setFocusedWindow(window);
9734 window->consumeFocusEvent(true);
9735
9736 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
9737 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
9738 window->assertNoEvents();
9739}
9740
9741TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009742 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009743 auto window = owner.createWindow();
9744 auto spy = owner.createWindow();
9745 spy->setSpy(true);
9746 spy->setTrustedOverlay(true);
9747 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
9748
9749 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9750 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9751 spy->consumeMotionDown();
9752 window->consumeMotionDown();
9753}
9754
9755TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009756 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009757 auto window = owner.createWindow();
9758
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009759 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009760 auto randosSpy = rando.createWindow();
9761 randosSpy->setSpy(true);
9762 randosSpy->setTrustedOverlay(true);
9763 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9764
9765 // The event is targeted at owner's window, so injection should succeed, but the spy should
9766 // not receive the event.
9767 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9768 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9769 randosSpy->assertNoEvents();
9770 window->consumeMotionDown();
9771}
9772
9773TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009774 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009775 auto window = owner.createWindow();
9776
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009777 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009778 auto randosSpy = rando.createWindow();
9779 randosSpy->setSpy(true);
9780 randosSpy->setTrustedOverlay(true);
9781 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
9782
9783 // A user that has injection permission can inject into any window.
9784 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9785 injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
9786 ADISPLAY_ID_DEFAULT));
9787 randosSpy->consumeMotionDown();
9788 window->consumeMotionDown();
9789
9790 setFocusedWindow(randosSpy);
9791 randosSpy->consumeFocusEvent(true);
9792
9793 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
9794 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
9795 window->assertNoEvents();
9796}
9797
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009798TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009799 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009800 auto window = owner.createWindow();
9801
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009802 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +00009803 auto randosWindow = rando.createWindow();
9804 randosWindow->setFrame(Rect{-10, -10, -5, -5});
9805 randosWindow->setWatchOutsideTouch(true);
9806 mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
9807
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009808 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +00009809 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
9810 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
9811 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -07009812 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +00009813}
9814
Garfield Tane84e6f92019-08-29 17:28:41 -07009815} // namespace android::inputdispatcher