blob: fcb5ab0183431399eafc9762768ff4dfa0a2fe90 [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"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000019#include "FakeInputTracingBackend.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000020#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080021
Cody Heiner166a5af2023-07-07 12:25:00 -070022#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000023#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070024#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080025#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080026#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070027#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070028#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000029#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000030#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080032#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080033#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080034#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100035#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070036#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070037#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080038#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080039#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100040
Garfield Tan1c7bc862020-01-28 13:24:04 -080041#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080042#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070043#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080044#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080045#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080046
Garfield Tan1c7bc862020-01-28 13:24:04 -080047using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050048using android::gui::FocusRequest;
49using android::gui::TouchOcclusionMode;
50using android::gui::WindowInfo;
51using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080052using android::os::InputEventInjectionResult;
53using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080054
Garfield Tane84e6f92019-08-29 17:28:41 -070055namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080056
Dominik Laskowski2f01d772022-03-23 16:01:29 -070057using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080058using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000059using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070060
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070061namespace {
62
Michael Wrightd02c5b62014-02-10 15:10:22 -080063// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000064static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080065
66// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000067static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080068static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
Jeff Brownf086ddb2014-02-11 14:28:48 -080070// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000071static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
72static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080073
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000074// Ensure common actions are interchangeable between keys and motions for convenience.
75static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
76static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080077static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
78static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
79static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
80static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070081static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080082static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070083static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080084static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080085static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086/**
87 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
88 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
89 * index 0) is the new pointer going down. The same pointer could have been placed at a different
90 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
91 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
92 * pointer id=0 leaves but the pointer id=1 remains.
93 */
94static constexpr int32_t POINTER_0_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080096static constexpr int32_t POINTER_1_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000098static constexpr int32_t POINTER_2_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000100static constexpr int32_t POINTER_3_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000102static constexpr int32_t POINTER_0_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800104static constexpr int32_t POINTER_1_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000106static constexpr int32_t POINTER_2_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108
Antonio Kantek15beb512022-06-13 22:35:41 +0000109// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000110static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000111static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700120/**
121 * If we expect to receive the event, the timeout can be made very long. When the test are running
122 * correctly, we will actually never wait until the end of the timeout because the wait will end
123 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
124 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
125 * developer can see the failure quickly (on human scale).
126 */
127static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
128/**
129 * When no event is expected, we can have a very short timeout. A large value here would slow down
130 * the tests. In the unlikely event of system being too slow, the event may still be present but the
131 * timeout would complete before it is consumed. This would result in test flakiness. If this
132 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
133 * would get noticed and addressed quickly.
134 */
135static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
136
Arthur Hungc539dbb2022-12-08 07:45:36 +0000137static constexpr int expectedWallpaperFlags =
138 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
139
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800140using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
141
Gang Wang342c9272020-01-13 13:15:04 -0500142/**
143 * Return a DOWN key event with KEYCODE_A.
144 */
145static KeyEvent getTestKeyEvent() {
146 KeyEvent event;
147
Garfield Tanfbe732e2020-01-24 11:26:14 -0800148 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
149 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
150 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500151 return event;
152}
153
Michael Wrightd02c5b62014-02-10 15:10:22 -0800154// --- FakeInputDispatcherPolicy ---
155
156class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000157 struct AnrResult {
158 sp<IBinder> token{};
Prabir Pradhanfc364722024-02-08 17:51:20 +0000159 std::optional<gui::Pid> pid{};
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000160 };
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800161 /* Stores data about a user-activity-poke event from the dispatcher. */
162 struct UserActivityPokeEvent {
163 nsecs_t eventTime;
164 int32_t eventType;
165 int32_t displayId;
166
167 bool operator==(const UserActivityPokeEvent& rhs) const = default;
168
169 friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
170 os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
171 << ", displayId=" << ev.displayId << "]";
172 return os;
173 }
174 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800175
Michael Wrightd02c5b62014-02-10 15:10:22 -0800176public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 FakeInputDispatcherPolicy() = default;
178 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800179
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800180 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700181 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700182 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700183 EXPECT_EQ(event.getDisplayId(), args.displayId);
184
185 const auto& keyEvent = static_cast<const KeyEvent&>(event);
186 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
187 EXPECT_EQ(keyEvent.getAction(), args.action);
188 });
Jackal Guof9696682018-10-05 12:23:23 +0800189 }
190
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700191 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
192 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700193 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700194 EXPECT_EQ(event.getDisplayId(), args.displayId);
195
196 const auto& motionEvent = static_cast<const MotionEvent&>(event);
197 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
198 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000199 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
200 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
201 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
202 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700203 });
Jackal Guof9696682018-10-05 12:23:23 +0800204 }
205
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700206 void assertFilterInputEventWasNotCalled() {
207 std::scoped_lock lock(mLock);
208 ASSERT_EQ(nullptr, mFilteredEvent);
209 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800211 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700212 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800213 ASSERT_TRUE(mConfigurationChangedTime)
214 << "Timed out waiting for configuration changed call";
215 ASSERT_EQ(*mConfigurationChangedTime, when);
216 mConfigurationChangedTime = std::nullopt;
217 }
218
219 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700220 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800221 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800222 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800223 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
224 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
225 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
226 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
227 mLastNotifySwitch = std::nullopt;
228 }
229
chaviwfd6d3512019-03-25 13:23:49 -0700230 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700231 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800232 ASSERT_EQ(touchedToken, mOnPointerDownToken);
233 mOnPointerDownToken.clear();
234 }
235
236 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700237 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800238 ASSERT_TRUE(mOnPointerDownToken == nullptr)
239 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700240 }
241
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700242 // This function must be called soon after the expected ANR timer starts,
243 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700245 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500246 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800247 std::unique_lock lock(mLock);
248 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500249 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800250 ASSERT_NO_FATAL_FAILURE(
251 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500252 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700253 }
254
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000255 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800256 const sp<WindowInfoHandle>& window) {
257 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
258 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
259 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500260 }
261
Prabir Pradhanedd96402022-02-15 01:46:16 -0800262 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
263 const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000264 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800265 std::unique_lock lock(mLock);
266 android::base::ScopedLockAssertion assumeLocked(mLock);
267 AnrResult result;
268 ASSERT_NO_FATAL_FAILURE(result =
269 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000270 ASSERT_EQ(expectedToken, result.token);
271 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500272 }
273
Prabir Pradhanedd96402022-02-15 01:46:16 -0800274 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000275 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500276 std::unique_lock lock(mLock);
277 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800278 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
279 const auto& [token, _] = result;
280 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000281 }
282
Prabir Pradhanedd96402022-02-15 01:46:16 -0800283 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanfc364722024-02-08 17:51:20 +0000284 std::optional<gui::Pid> expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800285 std::unique_lock lock(mLock);
286 android::base::ScopedLockAssertion assumeLocked(mLock);
287 AnrResult result;
288 ASSERT_NO_FATAL_FAILURE(
289 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000290 ASSERT_EQ(expectedToken, result.token);
291 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800292 }
293
294 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000295 sp<IBinder> getResponsiveWindowToken() {
296 std::unique_lock lock(mLock);
297 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800298 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
299 const auto& [token, _] = result;
300 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700301 }
302
303 void assertNotifyAnrWasNotCalled() {
304 std::scoped_lock lock(mLock);
305 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800306 ASSERT_TRUE(mAnrWindows.empty());
307 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500308 << "ANR was not called, but please also consume the 'connection is responsive' "
309 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700310 }
311
Hiroki Sato25040232024-02-22 17:21:22 +0900312 PointerCaptureRequest assertSetPointerCaptureCalled(const sp<WindowInfoHandle>& window,
313 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800314 std::unique_lock lock(mLock);
315 base::ScopedLockAssertion assumeLocked(mLock);
316
Hiroki Sato25040232024-02-22 17:21:22 +0900317 if (!mPointerCaptureChangedCondition
318 .wait_for(lock, 100ms, [this, enabled, window]() REQUIRES(mLock) {
319 if (enabled) {
320 return mPointerCaptureRequest->isEnable() &&
321 mPointerCaptureRequest->window == window->getToken();
322 } else {
323 return !mPointerCaptureRequest->isEnable();
324 }
325 })) {
326 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << window->getName() << ", "
327 << enabled << ") to be called.";
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000328 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800329 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000330 auto request = *mPointerCaptureRequest;
331 mPointerCaptureRequest.reset();
332 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800333 }
334
335 void assertSetPointerCaptureNotCalled() {
336 std::unique_lock lock(mLock);
337 base::ScopedLockAssertion assumeLocked(mLock);
338
339 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000340 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800341 "enabled = "
Hiroki Sato25040232024-02-22 17:21:22 +0900342 << std::to_string(mPointerCaptureRequest->isEnable());
Prabir Pradhan99987712020-11-10 18:43:05 -0800343 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000344 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800345 }
346
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700347 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
348 const sp<IBinder>& targetToken) {
349 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800350 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800351 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800352 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800353 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800354 }
355
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800356 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
357 std::unique_lock lock(mLock);
358 base::ScopedLockAssertion assumeLocked(mLock);
359 std::optional<sp<IBinder>> receivedToken =
360 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
361 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000362 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800363 ASSERT_EQ(token, *receivedToken);
364 }
365
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800366 /**
367 * Set policy timeout. A value of zero means next key will not be intercepted.
368 */
369 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
370 mInterceptKeyTimeout = timeout;
371 }
372
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800373 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
374
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700375 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
376
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800377 void assertUserActivityNotPoked() {
378 std::unique_lock lock(mLock);
379 base::ScopedLockAssertion assumeLocked(mLock);
380
381 std::optional<UserActivityPokeEvent> pokeEvent =
382 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
383 mNotifyUserActivity);
384
385 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000386 }
387
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800388 /**
389 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
390 * cleared after this call.
391 *
392 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
393 * earliest recorded poke event.
394 */
395 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
396 std::unique_lock lock(mLock);
397 base::ScopedLockAssertion assumeLocked(mLock);
398
399 std::optional<UserActivityPokeEvent> pokeEvent =
400 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
401 mNotifyUserActivity);
402 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
403
404 if (expectedPokeEvent) {
405 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
406 }
Josep del Riob3981622023-04-18 15:49:45 +0000407 }
408
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000409 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000410 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
411 }
412
413 void assertNotifyDeviceInteractionWasNotCalled() {
414 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
415 }
416
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000417 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
418 std::scoped_lock lock(mLock);
419 mUnhandledKeyHandler = handler;
420 }
421
422 void assertUnhandledKeyReported(int32_t keycode) {
423 std::unique_lock lock(mLock);
424 base::ScopedLockAssertion assumeLocked(mLock);
425 std::optional<int32_t> unhandledKeycode =
426 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
427 mNotifyUnhandledKey);
428 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
429 ASSERT_EQ(unhandledKeycode, keycode);
430 }
431
432 void assertUnhandledKeyNotReported() {
433 std::unique_lock lock(mLock);
434 base::ScopedLockAssertion assumeLocked(mLock);
435 std::optional<int32_t> unhandledKeycode =
436 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
437 mNotifyUnhandledKey);
438 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
439 }
440
Michael Wrightd02c5b62014-02-10 15:10:22 -0800441private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700442 std::mutex mLock;
443 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
444 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
445 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
446 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800447
Prabir Pradhan99987712020-11-10 18:43:05 -0800448 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000449
450 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800451
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700452 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700453 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800454 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
455 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700456 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800457 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
458 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700459
arthurhungf452d0b2021-01-06 00:19:52 +0800460 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800461 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800462
463 std::condition_variable mNotifyUserActivity;
464 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800465
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800466 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
467
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700468 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
469
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000470 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000471
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000472 std::condition_variable mNotifyUnhandledKey;
473 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
474 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
475
Prabir Pradhanedd96402022-02-15 01:46:16 -0800476 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
477 // for a specific container to become non-empty. When the container is non-empty, return the
478 // first entry from the container and erase it.
479 template <class T>
480 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
481 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
482 // If there is an ANR, Dispatcher won't be idle because there are still events
483 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
484 // before checking if ANR was called.
485 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
486 // to provide it some time to act. 100ms seems reasonable.
487 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
488 const std::chrono::time_point start = std::chrono::steady_clock::now();
489 std::optional<T> token =
490 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
491 if (!token.has_value()) {
492 ADD_FAILURE() << "Did not receive the ANR callback";
493 return {};
494 }
495
496 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
497 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
498 // the dispatcher started counting before this function was called
499 if (std::chrono::abs(timeout - waited) > 100ms) {
500 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
501 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
502 << "ms, but waited "
503 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
504 << "ms instead";
505 }
506 return *token;
507 }
508
509 template <class T>
510 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
511 std::queue<T>& storage,
512 std::unique_lock<std::mutex>& lock,
513 std::condition_variable& condition)
514 REQUIRES(mLock) {
515 condition.wait_for(lock, timeout,
516 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
517 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800518 return std::nullopt;
519 }
520 T item = storage.front();
521 storage.pop();
522 return std::make_optional(item);
523 }
524
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600525 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700526 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800527 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800528 }
529
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000530 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800531 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700532 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000533 mAnrWindows.push({connectionToken, pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700534 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500535 }
536
Prabir Pradhanedd96402022-02-15 01:46:16 -0800537 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000538 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500539 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000540 mResponsiveWindows.push({connectionToken, pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500541 mNotifyAnr.notify_all();
542 }
543
544 void notifyNoFocusedWindowAnr(
545 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
546 std::scoped_lock lock(mLock);
547 mAnrApplications.push(applicationHandle);
548 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800549 }
550
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800551 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
552 std::scoped_lock lock(mLock);
553 mBrokenInputChannels.push(connectionToken);
554 mNotifyInputChannelBroken.notify_all();
555 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800556
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600557 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700558
Chris Yef59a2f42020-10-16 12:55:26 -0700559 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
560 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
561 const std::vector<float>& values) override {}
562
563 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
564 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000565
Chris Yefb552902021-02-03 17:18:37 -0800566 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
567
Prabir Pradhana41d2442023-04-20 21:30:40 +0000568 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700569 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000570 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700571 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000572 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
573 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800574 break;
575 }
576
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700577 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000578 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
579 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800580 break;
581 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700582 default: {
583 ADD_FAILURE() << "Should only filter keys or motions";
584 break;
585 }
Jackal Guof9696682018-10-05 12:23:23 +0800586 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800587 return true;
588 }
589
Prabir Pradhana41d2442023-04-20 21:30:40 +0000590 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
591 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800592 // Clear intercept state when we handled the event.
593 mInterceptKeyTimeout = 0ms;
594 }
595 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800596
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800597 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800598
Prabir Pradhana41d2442023-04-20 21:30:40 +0000599 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800600 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
601 // Clear intercept state so we could dispatch the event in next wake.
602 mInterceptKeyTimeout = 0ms;
603 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800604 }
605
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000606 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000607 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000608 std::scoped_lock lock(mLock);
609 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
610 mNotifyUnhandledKey.notify_all();
611 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800612 }
613
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600614 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
615 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700616 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800617 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
618 * essentially a passthrough for notifySwitch.
619 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000620 mLastNotifySwitch =
621 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800622 }
623
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800624 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000625 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800626 mNotifyUserActivity.notify_all();
627 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000628 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800629
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700630 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
631 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
632 }
633
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600634 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700635 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700636 mOnPointerDownToken = newToken;
637 }
638
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000639 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800640 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000641 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800642 mPointerCaptureChangedCondition.notify_all();
643 }
644
arthurhungf452d0b2021-01-06 00:19:52 +0800645 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
646 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800647 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800648 mDropTargetWindowToken = token;
649 }
650
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000651 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000652 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000653 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
654 }
655
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700656 void assertFilterInputEventWasCalledInternal(
657 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700658 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800659 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700660 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800661 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800662 }
Prabir Pradhanbf3c8322024-02-23 02:38:36 +0000663
664 gui::Uid getPackageUid(std::string) override { return gui::Uid::INVALID; }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800665};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700666} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667
Michael Wrightd02c5b62014-02-10 15:10:22 -0800668// --- InputDispatcherTest ---
669
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000670// The trace is a global variable for now, to avoid having to pass it into all of the
671// FakeWindowHandles created throughout the tests.
672// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
673static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
674
Michael Wrightd02c5b62014-02-10 15:10:22 -0800675class InputDispatcherTest : public testing::Test {
676protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000677 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700678 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800679
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000680 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000681 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000682 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000683 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
684 std::make_unique<FakeInputTracingBackend>(
685 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700686
Harry Cutts101ee9b2023-07-06 18:04:14 +0000687 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000688 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700689 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 }
691
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000692 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000693 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700694 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000695 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700696 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800697 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700698
699 /**
700 * Used for debugging when writing the test
701 */
702 void dumpDispatcherState() {
703 std::string dump;
704 mDispatcher->dump(dump);
705 std::stringstream ss(dump);
706 std::string to;
707
708 while (std::getline(ss, to, '\n')) {
709 ALOGE("%s", to.c_str());
710 }
711 }
Vishnu Nair958da932020-08-21 17:12:37 -0700712
Chavi Weingarten847e8512023-03-29 00:26:09 +0000713 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700714 FocusRequest request;
715 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000716 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700717 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
718 request.displayId = window->getInfo()->displayId;
719 mDispatcher->setFocusedWindow(request);
720 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800721};
722
Michael Wrightd02c5b62014-02-10 15:10:22 -0800723TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
724 KeyEvent event;
725
726 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800727 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
728 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000729 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600730 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800731 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000732 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000733 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800734 << "Should reject key events with undefined action.";
735
736 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800737 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
738 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600739 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800740 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000741 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000742 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800743 << "Should reject key events with ACTION_MULTIPLE.";
744}
745
746TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
747 MotionEvent event;
748 PointerProperties pointerProperties[MAX_POINTERS + 1];
749 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800750 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800751 pointerProperties[i].clear();
752 pointerProperties[i].id = i;
753 pointerCoords[i].clear();
754 }
755
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800756 // Some constants commonly used below
757 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
758 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
759 constexpr int32_t metaState = AMETA_NONE;
760 constexpr MotionClassification classification = MotionClassification::NONE;
761
chaviw9eaa22c2020-07-01 16:21:27 -0700762 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800763 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800764 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000765 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700766 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700767 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
768 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000769 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000771 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000772 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800773 << "Should reject motion events with undefined action.";
774
775 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800776 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800777 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
778 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
779 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
780 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000781 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000783 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000784 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800785 << "Should reject motion events with pointer down index too large.";
786
Garfield Tanfbe732e2020-01-24 11:26:14 -0800787 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700788 AMOTION_EVENT_ACTION_POINTER_DOWN |
789 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700790 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
791 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700792 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000793 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800794 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000795 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000796 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800797 << "Should reject motion events with pointer down index too small.";
798
799 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800800 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800801 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
802 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
803 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
804 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000805 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800806 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000807 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000808 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800809 << "Should reject motion events with pointer up index too large.";
810
Garfield Tanfbe732e2020-01-24 11:26:14 -0800811 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700812 AMOTION_EVENT_ACTION_POINTER_UP |
813 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700814 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
815 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700816 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000817 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800818 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000819 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000820 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800821 << "Should reject motion events with pointer up index too small.";
822
823 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800824 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
825 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700826 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700827 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
828 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000829 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800830 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000831 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000832 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800833 << "Should reject motion events with 0 pointers.";
834
Garfield Tanfbe732e2020-01-24 11:26:14 -0800835 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
836 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700837 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700838 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
839 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000840 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800841 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000842 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000843 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800844 << "Should reject motion events with more than MAX_POINTERS pointers.";
845
846 // Rejects motion events with invalid pointer ids.
847 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800848 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
849 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700850 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700851 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
852 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000853 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800854 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000855 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000856 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800857 << "Should reject motion events with pointer ids less than 0.";
858
859 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800860 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
861 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700862 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700863 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
864 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000865 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800866 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000867 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000868 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800869 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
870
871 // Rejects motion events with duplicate pointer ids.
872 pointerProperties[0].id = 1;
873 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800874 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
875 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700876 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700877 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
878 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000879 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800880 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000881 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000882 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800883 << "Should reject motion events with duplicate pointer ids.";
884}
885
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800886/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
887
888TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
889 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000890 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800891 ASSERT_TRUE(mDispatcher->waitForIdle());
892
893 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
894}
895
896TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000897 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
898 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000899 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000900 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800901
902 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
903 args.policyFlags |= POLICY_FLAG_TRUSTED;
904 mFakePolicy->assertNotifySwitchWasCalled(args);
905}
906
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700907namespace {
908
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700909static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700910// Default input dispatching timeout if there is no focused application or paused window
911// from which to determine an appropriate dispatching timeout.
912static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
913 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
914 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800915
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800916class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800917public:
Garfield Tan15601662020-09-22 15:32:38 -0700918 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700919 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800920
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800921 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
922 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700923 if (!consumeSeq) {
924 return nullptr;
925 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000926 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800927 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700928 }
929
930 /**
931 * Receive an event without acknowledging it.
932 * Return the sequence number that could later be used to send finished signal.
933 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800934 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
935 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800936 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800937 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800938
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 std::chrono::time_point start = std::chrono::steady_clock::now();
940 status_t status = WOULD_BLOCK;
941 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800942 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700943 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800944 &rawEventPtr);
945 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800946 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700947 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800948 break;
949 }
950 }
951
952 if (status == WOULD_BLOCK) {
953 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800954 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800955 }
956
957 if (status != OK) {
958 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800959 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800960 }
961 if (event == nullptr) {
962 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800963 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800964 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700965 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800966
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700967 /**
968 * To be used together with "receiveEvent" to complete the consumption of an event.
969 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000970 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700971 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700972 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800973 }
974
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000975 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700976 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000977 ASSERT_EQ(OK, status);
978 }
979
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000981 std::optional<int32_t> expectedDisplayId,
982 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800983 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800984
985 ASSERT_NE(nullptr, event) << mName.c_str()
986 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800987 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
989 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800990
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedDisplayId.has_value()) {
992 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994
Tiger Huang8664f8c2018-10-11 19:14:35 +0800995 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800997 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700998 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000999 if (expectedFlags.has_value()) {
1000 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
1001 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001002 break;
1003 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001004 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001005 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -07001006 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001007 if (expectedFlags.has_value()) {
1008 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1009 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001010 break;
1011 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001012 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001013 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1014 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001015 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001016 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1017 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001018 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001019 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1020 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001021 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001022 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1023 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001024 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001025 }
1026
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001027 std::unique_ptr<MotionEvent> consumeMotion() {
1028 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001029
1030 if (event == nullptr) {
1031 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1032 return nullptr;
1033 }
1034
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001035 if (event->getType() != InputEventType::MOTION) {
1036 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001037 return nullptr;
1038 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001039 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001040 }
1041
1042 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001043 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001044 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1045 ASSERT_THAT(*motionEvent, matcher);
1046 }
1047
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001048 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001049 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001050 ASSERT_NE(nullptr, event) << mName.c_str()
1051 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001052 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1053 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001054
1055 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1056 << mName.c_str() << ": event displayId should always be NONE.";
1057
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001058 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1059 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001060 }
1061
Prabir Pradhan99987712020-11-10 18:43:05 -08001062 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001063 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001064 ASSERT_NE(nullptr, event) << mName.c_str()
1065 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001066 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1067 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001068
1069 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1070 << mName.c_str() << ": event displayId should always be NONE.";
1071
1072 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1073 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1074 }
1075
arthurhungb89ccb02020-12-30 16:19:01 +08001076 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001077 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001078 ASSERT_NE(nullptr, event) << mName.c_str()
1079 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001080 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001081
1082 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1083 << mName.c_str() << ": event displayId should always be NONE.";
1084
1085 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1086 EXPECT_EQ(isExiting, dragEvent.isExiting());
1087 EXPECT_EQ(x, dragEvent.getX());
1088 EXPECT_EQ(y, dragEvent.getY());
1089 }
1090
Antonio Kantekf16f2832021-09-28 04:39:20 +00001091 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001092 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001093 ASSERT_NE(nullptr, event) << mName.c_str()
1094 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001095 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1096 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001097
1098 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1099 << mName.c_str() << ": event displayId should always be NONE.";
1100 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1101 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1102 }
1103
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001104 void assertNoEvents(std::chrono::milliseconds timeout) {
1105 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001106 if (event == nullptr) {
1107 return;
1108 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001109 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001110 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001111 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001112 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001113 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001114 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001115 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001116 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1117 ADD_FAILURE() << "Received focus event, hasFocus = "
1118 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001119 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001120 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1121 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1122 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001123 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001124 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1125 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1126 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001127 }
1128 FAIL() << mName.c_str()
1129 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001130 }
1131
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001132 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001133
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001134 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001135
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001136private:
1137 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001138 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001139
1140 std::string mName;
1141};
1142
chaviw3277faf2021-05-19 16:45:23 -05001143class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001144public:
1145 static const int32_t WIDTH = 600;
1146 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001147
Chris Yea209fde2020-07-22 13:54:51 -07001148 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001149 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001150 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001151 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001152 sp<IBinder> token;
1153 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001154 base::Result<std::unique_ptr<InputChannel>> channel =
1155 dispatcher->createInputChannel(name);
1156 token = (*channel)->getConnectionToken();
1157 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001158 }
1159
1160 inputApplicationHandle->updateInfo();
1161 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1162
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001163 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001164 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001165 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001166 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001167 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001168 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001169 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001170 mInfo.globalScaleFactor = 1.0;
1171 mInfo.touchableRegion.clear();
1172 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001173 mInfo.ownerPid = WINDOW_PID;
1174 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001175 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001176 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001177 }
1178
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001179 sp<FakeWindowHandle> clone(int32_t displayId) {
1180 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1181 handle->mInfo = mInfo;
1182 handle->mInfo.displayId = displayId;
1183 handle->mInfo.id = sId++;
1184 handle->mInputReceiver = mInputReceiver;
1185 return handle;
1186 }
1187
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001188 void setTouchable(bool touchable) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1190 }
chaviwd1c23182019-12-20 18:44:56 -08001191
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001192 void setFocusable(bool focusable) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1194 }
1195
1196 void setVisible(bool visible) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1198 }
Vishnu Nair958da932020-08-21 17:12:37 -07001199
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001200 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001201 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001202 }
1203
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001204 void setPaused(bool paused) {
1205 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1206 }
1207
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001208 void setPreventSplitting(bool preventSplitting) {
1209 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001210 }
1211
1212 void setSlippery(bool slippery) {
1213 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1214 }
1215
1216 void setWatchOutsideTouch(bool watchOutside) {
1217 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1218 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001219
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001220 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1221
1222 void setInterceptsStylus(bool interceptsStylus) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1224 }
1225
1226 void setDropInput(bool dropInput) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1228 }
1229
1230 void setDropInputIfObscured(bool dropInputIfObscured) {
1231 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1232 }
1233
1234 void setNoInputChannel(bool noInputChannel) {
1235 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1236 }
1237
Josep del Riob3981622023-04-18 15:49:45 +00001238 void setDisableUserActivity(bool disableUserActivity) {
1239 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1240 }
1241
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001242 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1243 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1244 shouldGlobalStylusBlockTouch);
1245 }
1246
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001247 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1248
chaviw3277faf2021-05-19 16:45:23 -05001249 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001250
Bernardo Rufino7393d172021-02-26 13:56:11 +00001251 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1252
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001253 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001254 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001255 mInfo.touchableRegion.clear();
1256 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001257
1258 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1259 ui::Transform translate;
1260 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1261 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001262 }
1263
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001264 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1265
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001266 void setIsWallpaper(bool isWallpaper) {
1267 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1268 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001269
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001270 void setDupTouchToWallpaper(bool hasWallpaper) {
1271 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1272 }
chaviwd1c23182019-12-20 18:44:56 -08001273
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001274 void setTrustedOverlay(bool trustedOverlay) {
1275 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1276 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001277
chaviw9eaa22c2020-07-01 16:21:27 -07001278 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1279 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1280 }
1281
1282 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001283
yunho.shinf4a80b82020-11-16 21:13:57 +09001284 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1285
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001286 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1287 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1288 if (event == nullptr) {
1289 ADD_FAILURE() << "No event";
1290 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001291 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001292 if (event->getType() != InputEventType::KEY) {
1293 ADD_FAILURE() << "Instead of key event, got " << event;
1294 return nullptr;
1295 }
1296 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001297 }
1298
1299 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001300 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1301 ASSERT_NE(nullptr, keyEvent);
1302 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001303 }
1304
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001305 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001306 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1307 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001308 }
1309
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001310 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001311 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1312 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001313 }
1314
Svet Ganov5d3bc372020-01-26 23:11:07 -08001315 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001316 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001317 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1318 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001319 }
1320
1321 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001322 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001323 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1324 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001325 }
1326
1327 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001328 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001329 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1330 }
1331
1332 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1333 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001334 consumeMotionEvent(
1335 AllOf(WithMotionAction(ACTION_DOWN),
1336 testing::Conditional(expectedDisplayId.has_value(),
1337 WithDisplayId(*expectedDisplayId), testing::_),
1338 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1339 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001340 }
1341
Svet Ganov5d3bc372020-01-26 23:11:07 -08001342 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001343 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1344 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001345 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001346 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001347 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1348 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001349 }
1350
1351 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001352 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001353 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001354 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001355 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1356 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001357 }
1358
1359 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001360 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001361 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1362 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001363 }
1364
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001365 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1366 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001367 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1368 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001369 }
1370
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001371 void consumeMotionOutsideWithZeroedCoords() {
1372 consumeMotionEvent(
1373 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001374 }
1375
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001376 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1377 ASSERT_NE(mInputReceiver, nullptr)
1378 << "Cannot consume events from a window with no receiver";
1379 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1380 }
1381
Prabir Pradhan99987712020-11-10 18:43:05 -08001382 void consumeCaptureEvent(bool hasCapture) {
1383 ASSERT_NE(mInputReceiver, nullptr)
1384 << "Cannot consume events from a window with no receiver";
1385 mInputReceiver->consumeCaptureEvent(hasCapture);
1386 }
1387
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001388 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001389 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001390 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1391 if (event == nullptr) {
1392 ADD_FAILURE() << "No event";
1393 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001394 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001395 if (event->getType() != InputEventType::MOTION) {
1396 ADD_FAILURE() << "Instead of motion event, got " << *event;
1397 return nullptr;
1398 }
1399 std::unique_ptr<MotionEvent> motionEvent =
1400 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1401 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001402 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001403 }
1404
arthurhungb89ccb02020-12-30 16:19:01 +08001405 void consumeDragEvent(bool isExiting, float x, float y) {
1406 mInputReceiver->consumeDragEvent(isExiting, x, y);
1407 }
1408
Antonio Kantekf16f2832021-09-28 04:39:20 +00001409 void consumeTouchModeEvent(bool inTouchMode) {
1410 ASSERT_NE(mInputReceiver, nullptr)
1411 << "Cannot consume events from a window with no receiver";
1412 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1413 }
1414
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001415 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001416 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001417 }
1418
1419 void finishEvent(uint32_t sequenceNum) {
1420 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1421 mInputReceiver->finishEvent(sequenceNum);
1422 }
1423
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001424 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1425 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1426 mInputReceiver->sendTimeline(inputEventId, timeline);
1427 }
1428
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001429 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001430 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001431 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001432 return; // Can't receive events if the window does not have input channel
1433 }
1434 ASSERT_NE(nullptr, mInputReceiver)
1435 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001436 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001437 }
1438
chaviwaf87b3e2019-10-01 16:59:28 -07001439 sp<IBinder> getToken() { return mInfo.token; }
1440
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001441 const std::string& getName() { return mName; }
1442
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001443 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001444 mInfo.ownerPid = ownerPid;
1445 mInfo.ownerUid = ownerUid;
1446 }
1447
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001448 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001449
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001450 void destroyReceiver() { mInputReceiver = nullptr; }
1451
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001452 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1453
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001454 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001455 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001456 if (mInputReceiver == nullptr) {
1457 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1458 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001459 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001460 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001461 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001462 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001463 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001464 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001465 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001466
1467private:
1468 FakeWindowHandle(std::string name) : mName(name){};
1469 const std::string mName;
1470 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1471 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1472 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001473
1474 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1475 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1476 if (mInputReceiver == nullptr) {
1477 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1478 return std::make_pair(std::nullopt, nullptr);
1479 }
1480 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1481 const auto& [_, event] = out;
1482 expectReceivedEventTraced(event);
1483 return std::move(out);
1484 }
1485
1486 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1487 if (!event) {
1488 return;
1489 }
1490
1491 switch (event->getType()) {
1492 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001493 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001494 break;
1495 }
1496 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001497 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
1498 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001499 break;
1500 }
1501 default:
1502 break;
1503 }
1504 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001505};
1506
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001507std::atomic<int32_t> FakeWindowHandle::sId{1};
1508
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001509class FakeMonitorReceiver {
1510public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001511 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1512 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001513
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001514 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001515
1516 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001517 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1518 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001519 }
1520
1521 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001522 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1523 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001524 }
1525
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001526 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001527
1528 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001529 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1530 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001531 }
1532
1533 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001534 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1535 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001536 }
1537
1538 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001539 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1540 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001541 }
1542
1543 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001544 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001545 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1546 WithDisplayId(expectedDisplayId),
1547 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1548 }
1549
1550 void consumeMotionPointerDown(int32_t pointerIdx) {
1551 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1552 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001553 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1554 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001555 }
1556
1557 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001558 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001559 }
1560
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001561 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001562
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001563 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001564
1565private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001566 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001567};
1568
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001569static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001570 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001571 int32_t displayId = ADISPLAY_ID_NONE,
1572 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001573 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001574 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001575 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001576 KeyEvent event;
1577 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1578
1579 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001580 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001581 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1582 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001583
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001584 if (!allowKeyRepeat) {
1585 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1586 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001587 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001588 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001589}
1590
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001591static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1592 InputEventInjectionResult result =
1593 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1594 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1595 if (result != InputEventInjectionResult::TIMED_OUT) {
1596 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1597 }
1598}
1599
1600static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001601 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001602 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001603}
1604
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001605// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1606// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1607// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1609 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001610 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001611 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001612 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001613}
1614
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001615static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001616 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001617 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001618}
1619
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001620static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001621 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001622 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001623 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001624 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001625 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1626 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001627}
1628
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001629static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001630 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1631 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001632 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001633 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1634 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001635 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001636 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001637 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001638 MotionEventBuilder motionBuilder =
1639 MotionEventBuilder(action, source)
1640 .displayId(displayId)
1641 .eventTime(eventTime)
1642 .rawXCursorPosition(cursorPosition.x)
1643 .rawYCursorPosition(cursorPosition.y)
1644 .pointer(
1645 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1646 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1647 motionBuilder.downTime(eventTime);
1648 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001649
1650 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001651 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1652 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001653}
1654
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001655static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1656 int32_t displayId,
1657 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001658 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001659}
1660
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001661static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1662 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001663 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001664 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001665}
1666
Jackal Guof9696682018-10-05 12:23:23 +08001667static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1668 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1669 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001670 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1671 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1672 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001673
1674 return args;
1675}
1676
Josep del Riob3981622023-04-18 15:49:45 +00001677static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1678 int32_t displayId = ADISPLAY_ID_NONE) {
1679 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1680 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001681 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1682 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1683 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001684
1685 return args;
1686}
1687
1688static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1689 int32_t displayId = ADISPLAY_ID_NONE) {
1690 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1691 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001692 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1693 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1694 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001695
1696 return args;
1697}
1698
Prabir Pradhan678438e2023-04-13 19:32:51 +00001699[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1700 int32_t displayId,
1701 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001702 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001703 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1704 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1705 }
1706
chaviwd1c23182019-12-20 18:44:56 -08001707 PointerProperties pointerProperties[pointerCount];
1708 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001709
chaviwd1c23182019-12-20 18:44:56 -08001710 for (size_t i = 0; i < pointerCount; i++) {
1711 pointerProperties[i].clear();
1712 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001713 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001714
chaviwd1c23182019-12-20 18:44:56 -08001715 pointerCoords[i].clear();
1716 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1717 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1718 }
Jackal Guof9696682018-10-05 12:23:23 +08001719
1720 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1721 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001722 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1723 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1724 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001725 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001726 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001727 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001728 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001729
1730 return args;
1731}
1732
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001733static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1734 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1735}
1736
chaviwd1c23182019-12-20 18:44:56 -08001737static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1738 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1739}
1740
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001741static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1742 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001743 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1744 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001745}
1746
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001747} // namespace
1748
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001749/**
1750 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1751 * broken channel.
1752 */
1753TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1754 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1755 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001756 sp<FakeWindowHandle>::make(application, mDispatcher,
1757 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001758
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001759 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001760
1761 // Window closes its channel, but the window remains.
1762 window->destroyReceiver();
1763 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1764}
1765
Arthur Hungb92218b2018-08-14 12:00:21 +08001766TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001767 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001768 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1769 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001770
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001771 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001772 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001773 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001775
1776 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001777 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001778}
1779
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001780using InputDispatcherDeathTest = InputDispatcherTest;
1781
1782/**
1783 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1784 * should crash.
1785 */
1786TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1787 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1788 ScopedSilentDeath _silentDeath;
1789
1790 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1791 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1792 "Fake Window", ADISPLAY_ID_DEFAULT);
1793 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1794 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1795 "Incorrect WindowInfosUpdate provided");
1796}
1797
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001798TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001800 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1801 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001802
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001803 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001804 // Inject a MotionEvent to an unknown display.
1805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001806 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001807 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1808
1809 // Window should receive motion event.
1810 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1811}
1812
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001813/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001814 * Calling onWindowInfosChanged once should not cause any issues.
1815 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001816 * called twice.
1817 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001818TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001820 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1821 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001822 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001823
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001824 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001826 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001827 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001829
1830 // Window should receive motion event.
1831 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1832}
1833
1834/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001835 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001836 */
1837TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001838 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001839 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1840 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001841 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001843 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1844 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001846 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001847 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001849
1850 // Window should receive motion event.
1851 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1852}
1853
Arthur Hungb92218b2018-08-14 12:00:21 +08001854// The foreground window should receive the first touch down event.
1855TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001857 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001858 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001859 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001860 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001861
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001862 mDispatcher->onWindowInfosChanged(
1863 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001865 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001867
1868 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001869 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001870 windowSecond->assertNoEvents();
1871}
1872
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001873/**
1874 * Two windows: A top window, and a wallpaper behind the window.
1875 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1876 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001877 * 1. foregroundWindow <-- dup touch to wallpaper
1878 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001879 */
1880TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1881 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1882 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001883 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001884 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001885 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001886 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001887 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001888
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001889 mDispatcher->onWindowInfosChanged(
1890 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001892 injectMotionEvent(*mDispatcher,
1893 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1894 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1895 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1897
1898 // Both foreground window and its wallpaper should receive the touch down
1899 foregroundWindow->consumeMotionDown();
1900 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1901
1902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001903 injectMotionEvent(*mDispatcher,
1904 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1905 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1906 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1908
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001909 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001910 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1911
1912 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001913 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001914 foregroundWindow->consumeMotionCancel();
1915 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1916 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1917}
1918
1919/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001920 * Two fingers down on the window, and lift off the first finger.
1921 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1922 * contains a single pointer.
1923 */
1924TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1925 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1926 sp<FakeWindowHandle> window =
1927 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1928
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001929 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001930 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1932 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1933 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001934 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001935 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1936 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1937 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1938 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001939 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001940 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1941 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1942 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1943 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001944 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1945 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1946 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1947
1948 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001949 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001950 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1951 window->consumeMotionEvent(
1952 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1953}
1954
1955/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001956 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1957 * with the following differences:
1958 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1959 * clean up the connection.
1960 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1961 * Ensure that there's no crash in the dispatcher.
1962 */
1963TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1964 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1965 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001966 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001967 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001968 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001969 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001970 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001971
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001972 mDispatcher->onWindowInfosChanged(
1973 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001976 {100, 200}))
1977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1978
1979 // Both foreground window and its wallpaper should receive the touch down
1980 foregroundWindow->consumeMotionDown();
1981 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1982
1983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001984 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001985 ADISPLAY_ID_DEFAULT, {110, 200}))
1986 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1987
1988 foregroundWindow->consumeMotionMove();
1989 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1990
1991 // Wallpaper closes its channel, but the window remains.
1992 wallpaperWindow->destroyReceiver();
1993 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1994
1995 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1996 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001997 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001998 foregroundWindow->consumeMotionCancel();
1999}
2000
Arthur Hungc539dbb2022-12-08 07:45:36 +00002001class ShouldSplitTouchFixture : public InputDispatcherTest,
2002 public ::testing::WithParamInterface<bool> {};
2003INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
2004 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08002005/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002006 * A single window that receives touch (on top), and a wallpaper window underneath it.
2007 * The top window gets a multitouch gesture.
2008 * Ensure that wallpaper gets the same gesture.
2009 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002010TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002012 sp<FakeWindowHandle> foregroundWindow =
2013 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2014 foregroundWindow->setDupTouchToWallpaper(true);
2015 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016
2017 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002018 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002019 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002021 mDispatcher->onWindowInfosChanged(
2022 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002023
2024 // Touch down on top window
2025 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002026 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002027 {100, 100}))
2028 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2029
2030 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002031 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002032 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2033
2034 // Second finger down on the top window
2035 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002036 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002037 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002038 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2039 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002040 .build();
2041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002042 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002043 InputEventInjectionSync::WAIT_FOR_RESULT))
2044 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2045
Harry Cutts33476232023-01-30 19:57:29 +00002046 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2047 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002048 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049
2050 const MotionEvent secondFingerUpEvent =
2051 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2052 .displayId(ADISPLAY_ID_DEFAULT)
2053 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002054 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2055 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002056 .build();
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002058 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002059 InputEventInjectionSync::WAIT_FOR_RESULT))
2060 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2061 foregroundWindow->consumeMotionPointerUp(0);
2062 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2063
2064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002065 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002066 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2067 AINPUT_SOURCE_TOUCHSCREEN)
2068 .displayId(ADISPLAY_ID_DEFAULT)
2069 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002070 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002071 .x(100)
2072 .y(100))
2073 .build(),
2074 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002075 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2076 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2077 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078}
2079
2080/**
2081 * Two windows: a window on the left and window on the right.
2082 * A third window, wallpaper, is behind both windows, and spans both top windows.
2083 * The first touch down goes to the left window. A second pointer touches down on the right window.
2084 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2085 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2086 * ACTION_POINTER_DOWN(1).
2087 */
2088TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2089 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2090 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002091 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002092 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002093 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002094
2095 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002096 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002097 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002098 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002099
2100 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002101 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002102 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002103 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002104
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002105 mDispatcher->onWindowInfosChanged(
2106 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2107 {},
2108 0,
2109 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002110
2111 // Touch down on left window
2112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002113 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002114 {100, 100}))
2115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2116
2117 // Both foreground window and its wallpaper should receive the touch down
2118 leftWindow->consumeMotionDown();
2119 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2120
2121 // Second finger down on the right window
2122 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002123 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002124 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002125 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2126 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002127 .build();
2128 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002129 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002130 InputEventInjectionSync::WAIT_FOR_RESULT))
2131 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2132
2133 leftWindow->consumeMotionMove();
2134 // Since the touch is split, right window gets ACTION_DOWN
2135 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002136 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002137 expectedWallpaperFlags);
2138
2139 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002140 mDispatcher->onWindowInfosChanged(
2141 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002142 leftWindow->consumeMotionCancel();
2143 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2144 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2145
2146 // The pointer that's still down on the right window moves, and goes to the right window only.
2147 // As far as the dispatcher's concerned though, both pointers are still present.
2148 const MotionEvent secondFingerMoveEvent =
2149 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2150 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002151 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2152 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002153 .build();
2154 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002155 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002156 InputEventInjectionSync::WAIT_FOR_RESULT));
2157 rightWindow->consumeMotionMove();
2158
2159 leftWindow->assertNoEvents();
2160 rightWindow->assertNoEvents();
2161 wallpaperWindow->assertNoEvents();
2162}
2163
Arthur Hungc539dbb2022-12-08 07:45:36 +00002164/**
2165 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2166 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2167 * The right window should receive ACTION_DOWN.
2168 */
2169TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002170 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002171 sp<FakeWindowHandle> leftWindow =
2172 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2173 leftWindow->setFrame(Rect(0, 0, 200, 200));
2174 leftWindow->setDupTouchToWallpaper(true);
2175 leftWindow->setSlippery(true);
2176
2177 sp<FakeWindowHandle> rightWindow =
2178 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2179 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002180
2181 sp<FakeWindowHandle> wallpaperWindow =
2182 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2183 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002184
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002185 mDispatcher->onWindowInfosChanged(
2186 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2187 {},
2188 0,
2189 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002190
Arthur Hungc539dbb2022-12-08 07:45:36 +00002191 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002192 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002193 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002194 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002195 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002196
2197 // Both foreground window and its wallpaper should receive the touch down
2198 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002199 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2200
Arthur Hungc539dbb2022-12-08 07:45:36 +00002201 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002203 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002204 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002205 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2206
Arthur Hungc539dbb2022-12-08 07:45:36 +00002207 leftWindow->consumeMotionCancel();
2208 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2209 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002210}
2211
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002212/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002213 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2214 * interactive, it might stop sending this flag.
2215 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2216 * to have a consistent input stream.
2217 *
2218 * Test procedure:
2219 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2220 * DOWN (new gesture).
2221 *
2222 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2223 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2224 *
2225 * We technically just need a single window here, but we are using two windows (spy on top and a
2226 * regular window below) to emulate the actual situation where it happens on the device.
2227 */
2228TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2230 sp<FakeWindowHandle> spyWindow =
2231 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2232 spyWindow->setFrame(Rect(0, 0, 200, 200));
2233 spyWindow->setTrustedOverlay(true);
2234 spyWindow->setSpy(true);
2235
2236 sp<FakeWindowHandle> window =
2237 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2238 window->setFrame(Rect(0, 0, 200, 200));
2239
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002240 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002241 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002242
2243 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002244 mDispatcher->notifyMotion(
2245 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2246 .deviceId(touchDeviceId)
2247 .policyFlags(DEFAULT_POLICY_FLAGS)
2248 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2249 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002250
Prabir Pradhan678438e2023-04-13 19:32:51 +00002251 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2252 .deviceId(touchDeviceId)
2253 .policyFlags(DEFAULT_POLICY_FLAGS)
2254 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2255 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2256 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002257 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2258 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2259 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2260 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2261
2262 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002263 mDispatcher->notifyMotion(
2264 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2265 .deviceId(touchDeviceId)
2266 .policyFlags(0)
2267 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2268 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2269 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002270 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2271 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2272
2273 // We don't need to reset the device to reproduce the issue, but the reset event typically
2274 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002275 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002276
2277 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002278 mDispatcher->notifyMotion(
2279 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2280 .deviceId(touchDeviceId)
2281 .policyFlags(DEFAULT_POLICY_FLAGS)
2282 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2283 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002284 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2285 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2286
2287 // No more events
2288 spyWindow->assertNoEvents();
2289 window->assertNoEvents();
2290}
2291
2292/**
Linnan Li907ae732023-09-05 17:14:21 +08002293 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2294 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2295 * interactive, it might stop sending this flag.
2296 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2297 * the consistency of the hover event in this case.
2298 *
2299 * Test procedure:
2300 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2301 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2302 *
2303 * We expect to receive two full streams of hover events.
2304 */
2305TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2307
2308 sp<FakeWindowHandle> window =
2309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2310 window->setFrame(Rect(0, 0, 300, 300));
2311
2312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2313
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2315 .policyFlags(DEFAULT_POLICY_FLAGS)
2316 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2317 .build());
2318 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2319
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2321 .policyFlags(DEFAULT_POLICY_FLAGS)
2322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2323 .build());
2324 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2325
2326 // Send hover exit without the default policy flags.
2327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2328 .policyFlags(0)
2329 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2330 .build());
2331
2332 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2333
2334 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2335 // right event.
2336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2337 .policyFlags(DEFAULT_POLICY_FLAGS)
2338 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2339 .build());
2340 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2341
2342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2343 .policyFlags(DEFAULT_POLICY_FLAGS)
2344 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2345 .build());
2346 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2347
2348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2349 .policyFlags(DEFAULT_POLICY_FLAGS)
2350 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2351 .build());
2352 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2353}
2354
2355/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002356 * Two windows: a window on the left and a window on the right.
2357 * Mouse is hovered from the right window into the left window.
2358 * Next, we tap on the left window, where the cursor was last seen.
2359 * The second tap is done onto the right window.
2360 * The mouse and tap are from two different devices.
2361 * We technically don't need to set the downtime / eventtime for these events, but setting these
2362 * explicitly helps during debugging.
2363 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2364 * In the buggy implementation, a tap on the right window would cause a crash.
2365 */
2366TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2367 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2368 sp<FakeWindowHandle> leftWindow =
2369 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2370 leftWindow->setFrame(Rect(0, 0, 200, 200));
2371
2372 sp<FakeWindowHandle> rightWindow =
2373 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2374 rightWindow->setFrame(Rect(200, 0, 400, 200));
2375
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002376 mDispatcher->onWindowInfosChanged(
2377 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002378 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2379 // stale.
2380 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2381 const int32_t mouseDeviceId = 6;
2382 const int32_t touchDeviceId = 4;
2383 // Move the cursor from right
2384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002385 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002386 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2387 AINPUT_SOURCE_MOUSE)
2388 .deviceId(mouseDeviceId)
2389 .downTime(baseTime + 10)
2390 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002391 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002392 .build()));
2393 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2394
2395 // .. to the left window
2396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002397 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002398 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2399 AINPUT_SOURCE_MOUSE)
2400 .deviceId(mouseDeviceId)
2401 .downTime(baseTime + 10)
2402 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002404 .build()));
2405 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2406 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2407 // Now tap the left window
2408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002409 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002410 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2411 AINPUT_SOURCE_TOUCHSCREEN)
2412 .deviceId(touchDeviceId)
2413 .downTime(baseTime + 40)
2414 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002415 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002416 .build()));
2417 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2418 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2419
2420 // release tap
2421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002422 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002423 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2424 AINPUT_SOURCE_TOUCHSCREEN)
2425 .deviceId(touchDeviceId)
2426 .downTime(baseTime + 40)
2427 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002428 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002429 .build()));
2430 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2431
2432 // Tap the window on the right
2433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002434 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002435 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2436 AINPUT_SOURCE_TOUCHSCREEN)
2437 .deviceId(touchDeviceId)
2438 .downTime(baseTime + 60)
2439 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002440 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002441 .build()));
2442 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2443
2444 // release tap
2445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002446 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002447 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2448 AINPUT_SOURCE_TOUCHSCREEN)
2449 .deviceId(touchDeviceId)
2450 .downTime(baseTime + 60)
2451 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002452 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002453 .build()));
2454 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2455
2456 // No more events
2457 leftWindow->assertNoEvents();
2458 rightWindow->assertNoEvents();
2459}
2460
2461/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002462 * Start hovering in a window. While this hover is still active, make another window appear on top.
2463 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2464 * While the top window is present, the hovering is stopped.
2465 * Later, hovering gets resumed again.
2466 * Ensure that new hover gesture is handled correctly.
2467 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2468 * to the window that's currently being hovered over.
2469 */
2470TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2472 sp<FakeWindowHandle> window =
2473 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2474 window->setFrame(Rect(0, 0, 200, 200));
2475
2476 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002477 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002478
2479 // Start hovering in the window
2480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2482 .build());
2483 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2484
2485 // Now, an obscuring window appears!
2486 sp<FakeWindowHandle> obscuringWindow =
2487 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2488 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002489 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002490 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2491 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2492 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2493 obscuringWindow->setNoInputChannel(true);
2494 obscuringWindow->setFocusable(false);
2495 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002496 mDispatcher->onWindowInfosChanged(
2497 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002498
2499 // While this new obscuring window is present, the hovering is stopped
2500 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2501 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2502 .build());
2503 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2504
2505 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002507
2508 // And a new hover gesture starts.
2509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2510 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2511 .build());
2512 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2513}
2514
2515/**
2516 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2517 * the obscuring window.
2518 */
2519TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2521 sp<FakeWindowHandle> window =
2522 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2523 window->setFrame(Rect(0, 0, 200, 200));
2524
2525 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002526 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002527
2528 // Start hovering in the window
2529 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2530 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2531 .build());
2532 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2533
2534 // Now, an obscuring window appears!
2535 sp<FakeWindowHandle> obscuringWindow =
2536 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2537 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002538 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002539 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2540 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2541 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2542 obscuringWindow->setNoInputChannel(true);
2543 obscuringWindow->setFocusable(false);
2544 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002545 mDispatcher->onWindowInfosChanged(
2546 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002547
2548 // While this new obscuring window is present, the hovering continues. The event can't go to the
2549 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2551 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2552 .build());
2553 obscuringWindow->assertNoEvents();
2554 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2555
2556 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002557 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002558
2559 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2560 // so it should generate a HOVER_ENTER
2561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2562 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2563 .build());
2564 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2565
2566 // Now the MOVE should be getting dispatched normally
2567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2568 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2569 .build());
2570 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2571}
2572
2573/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002574 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2575 * events are delivered to the window.
2576 */
2577TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2579 sp<FakeWindowHandle> window =
2580 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2581 window->setFrame(Rect(0, 0, 200, 200));
2582 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2583
2584 // Start hovering in the window
2585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2586 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2587 .build());
2588 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2589
2590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2591 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2592 .build());
2593 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2594
2595 // Scroll with the mouse
2596 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2597 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2598 .build());
2599 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2600}
2601
2602using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2603
2604/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002605 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2606 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002607 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002608TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002609 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2610 sp<FakeWindowHandle> window =
2611 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2612 window->setFrame(Rect(0, 0, 200, 200));
2613
2614 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2615
2616 constexpr int32_t touchDeviceId = 4;
2617 constexpr int32_t stylusDeviceId = 2;
2618
2619 // Stylus down
2620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2621 .deviceId(stylusDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2623 .build());
2624 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2625
2626 // Touch down
2627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2628 .deviceId(touchDeviceId)
2629 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2630 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002631
2632 // Touch move
2633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2634 .deviceId(touchDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2636 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002638
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002639 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2641 .deviceId(stylusDeviceId)
2642 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2643 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002644 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2645 WithCoords(101, 111)));
2646
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002647 window->assertNoEvents();
2648}
2649
2650/**
2651 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002652 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002653 * Similar test as above, but with added SPY window.
2654 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002655TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002656 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2657 sp<FakeWindowHandle> window =
2658 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2659 sp<FakeWindowHandle> spyWindow =
2660 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2661 spyWindow->setFrame(Rect(0, 0, 200, 200));
2662 spyWindow->setTrustedOverlay(true);
2663 spyWindow->setSpy(true);
2664 window->setFrame(Rect(0, 0, 200, 200));
2665
2666 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2667
2668 constexpr int32_t touchDeviceId = 4;
2669 constexpr int32_t stylusDeviceId = 2;
2670
2671 // Stylus down
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2673 .deviceId(stylusDeviceId)
2674 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2675 .build());
2676 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2677 spyWindow->consumeMotionEvent(
2678 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2679
2680 // Touch down
2681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2682 .deviceId(touchDeviceId)
2683 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2684 .build());
2685
2686 // Touch move
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2690 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002691
2692 // Touch is ignored because stylus is already down
2693
2694 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2696 .deviceId(stylusDeviceId)
2697 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2698 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002699 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2700 WithCoords(101, 111)));
2701 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2702 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002703
2704 window->assertNoEvents();
2705 spyWindow->assertNoEvents();
2706}
2707
2708/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002709 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002710 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002711 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002712TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2714 sp<FakeWindowHandle> window =
2715 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2716 window->setFrame(Rect(0, 0, 200, 200));
2717
2718 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2719
2720 constexpr int32_t touchDeviceId = 4;
2721 constexpr int32_t stylusDeviceId = 2;
2722
2723 // Stylus down on the window
2724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2725 .deviceId(stylusDeviceId)
2726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2727 .build());
2728 window->consumeMotionEvent(
2729 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2730
2731 // Touch down on window
2732 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2733 .deviceId(touchDeviceId)
2734 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2735 .build());
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2737 .deviceId(touchDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2739 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002740
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002741 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002742
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002743 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2745 .deviceId(stylusDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2747 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002748 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2749 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002751 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2753 .deviceId(touchDeviceId)
2754 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2755 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002756 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002757}
2758
2759/**
2760 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002761 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002762 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002763TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2765 sp<FakeWindowHandle> window =
2766 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2767 window->setFrame(Rect(0, 0, 200, 200));
2768
2769 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2770
2771 constexpr int32_t touchDeviceId = 4;
2772 constexpr int32_t stylusDeviceId = 2;
2773
2774 // Touch down on window
2775 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2776 .deviceId(touchDeviceId)
2777 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2778 .build());
2779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2780 .deviceId(touchDeviceId)
2781 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2782 .build());
2783 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2784 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2785
2786 // Stylus hover on the window
2787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2788 .deviceId(stylusDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2790 .build());
2791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2792 .deviceId(stylusDeviceId)
2793 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2794 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002795 // Stylus hover movement causes touch to be canceled
2796 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2797 WithCoords(141, 146)));
2798 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2799 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2800 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2801 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002802
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002803 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002804 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2805 .deviceId(touchDeviceId)
2806 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2807 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002808
2809 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002810}
2811
2812/**
2813 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2814 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2815 * become active.
2816 */
2817TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2819 sp<FakeWindowHandle> window =
2820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2821 window->setFrame(Rect(0, 0, 200, 200));
2822
2823 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2824
2825 constexpr int32_t stylusDeviceId1 = 3;
2826 constexpr int32_t stylusDeviceId2 = 5;
2827
2828 // Touch down on window
2829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2830 .deviceId(stylusDeviceId1)
2831 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2832 .build());
2833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2834 .deviceId(stylusDeviceId1)
2835 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2836 .build());
2837 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2838 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2839
2840 // Second stylus down
2841 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2842 .deviceId(stylusDeviceId2)
2843 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2844 .build());
2845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2846 .deviceId(stylusDeviceId2)
2847 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2848 .build());
2849
2850 // First stylus is canceled, second one takes over.
2851 window->consumeMotionEvent(
2852 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2853 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2854 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2855
2856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2857 .deviceId(stylusDeviceId1)
2858 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2859 .build());
2860 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002861 window->assertNoEvents();
2862}
2863
2864/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002865 * One window. Touch down on the window. Then, stylus down on the window from another device.
2866 * Ensure that is canceled, because stylus down should be preferred over touch.
2867 */
2868TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2869 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2870 sp<FakeWindowHandle> window =
2871 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2872 window->setFrame(Rect(0, 0, 200, 200));
2873
2874 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2875
2876 constexpr int32_t touchDeviceId = 4;
2877 constexpr int32_t stylusDeviceId = 2;
2878
2879 // Touch down on window
2880 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2881 .deviceId(touchDeviceId)
2882 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2883 .build());
2884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2885 .deviceId(touchDeviceId)
2886 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2887 .build());
2888 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2889 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2890
2891 // Stylus down on the window
2892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2893 .deviceId(stylusDeviceId)
2894 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2895 .build());
2896 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2897 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2898
2899 // Subsequent stylus movements are delivered correctly
2900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2901 .deviceId(stylusDeviceId)
2902 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2903 .build());
2904 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2905 WithCoords(101, 111)));
2906}
2907
2908/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002909 * Two windows: a window on the left and a window on the right.
2910 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2911 * down. Then, on the left window, also place second touch pointer down.
2912 * This test tries to reproduce a crash.
2913 * In the buggy implementation, second pointer down on the left window would cause a crash.
2914 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002915TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2917 sp<FakeWindowHandle> leftWindow =
2918 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2919 leftWindow->setFrame(Rect(0, 0, 200, 200));
2920
2921 sp<FakeWindowHandle> rightWindow =
2922 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2923 rightWindow->setFrame(Rect(200, 0, 400, 200));
2924
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002925 mDispatcher->onWindowInfosChanged(
2926 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002927
2928 const int32_t touchDeviceId = 4;
2929 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002930
2931 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2933 .deviceId(mouseDeviceId)
2934 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002936 leftWindow->consumeMotionEvent(
2937 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2938
2939 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002940 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2941 .deviceId(mouseDeviceId)
2942 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2943 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2944 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002945
2946 leftWindow->consumeMotionEvent(
2947 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2948 leftWindow->consumeMotionEvent(
2949 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2950
Prabir Pradhan678438e2023-04-13 19:32:51 +00002951 mDispatcher->notifyMotion(
2952 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2953 .deviceId(mouseDeviceId)
2954 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2955 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2957 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002958 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2959
2960 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002961 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2962 .deviceId(touchDeviceId)
2963 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2964 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002965 leftWindow->assertNoEvents();
2966
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002967 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2968
2969 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002970 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2971 .deviceId(touchDeviceId)
2972 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2973 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2974 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002975 // Since this is now a new splittable pointer going down on the left window, and it's coming
2976 // from a different device, the current gesture in the left window (pointer down) should first
2977 // be canceled.
2978 leftWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002980 leftWindow->consumeMotionEvent(
2981 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2982 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2983 // current implementation.
2984 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2985 rightWindow->consumeMotionEvent(
2986 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2987
2988 leftWindow->assertNoEvents();
2989 rightWindow->assertNoEvents();
2990}
2991
2992/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993 * Two windows: a window on the left and a window on the right.
2994 * Mouse is hovered on the left window and stylus is hovered on the right window.
2995 */
2996TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2997 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2998 sp<FakeWindowHandle> leftWindow =
2999 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3000 leftWindow->setFrame(Rect(0, 0, 200, 200));
3001
3002 sp<FakeWindowHandle> rightWindow =
3003 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3004 rightWindow->setFrame(Rect(200, 0, 400, 200));
3005
3006 mDispatcher->onWindowInfosChanged(
3007 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3008
3009 const int32_t stylusDeviceId = 3;
3010 const int32_t mouseDeviceId = 6;
3011
3012 // Start hovering over the left window
3013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3014 .deviceId(mouseDeviceId)
3015 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3016 .build());
3017 leftWindow->consumeMotionEvent(
3018 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3019
3020 // Stylus hovered on right window
3021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3022 .deviceId(stylusDeviceId)
3023 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3024 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003025 rightWindow->consumeMotionEvent(
3026 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3027
3028 // Subsequent HOVER_MOVE events are dispatched correctly.
3029 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3030 .deviceId(mouseDeviceId)
3031 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3032 .build());
3033 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003034 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003035
3036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3037 .deviceId(stylusDeviceId)
3038 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3039 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003040 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003041 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003042
3043 leftWindow->assertNoEvents();
3044 rightWindow->assertNoEvents();
3045}
3046
3047/**
3048 * Three windows: a window on the left and a window on the right.
3049 * And a spy window that's positioned above all of them.
3050 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3051 * Check the stream that's received by the spy.
3052 */
3053TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3054 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3055
3056 sp<FakeWindowHandle> spyWindow =
3057 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3058 spyWindow->setFrame(Rect(0, 0, 400, 400));
3059 spyWindow->setTrustedOverlay(true);
3060 spyWindow->setSpy(true);
3061
3062 sp<FakeWindowHandle> leftWindow =
3063 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3064 leftWindow->setFrame(Rect(0, 0, 200, 200));
3065
3066 sp<FakeWindowHandle> rightWindow =
3067 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3068
3069 rightWindow->setFrame(Rect(200, 0, 400, 200));
3070
3071 mDispatcher->onWindowInfosChanged(
3072 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3073
3074 const int32_t stylusDeviceId = 1;
3075 const int32_t touchDeviceId = 2;
3076
3077 // Stylus down on the left window
3078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3079 .deviceId(stylusDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3081 .build());
3082 leftWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3084 spyWindow->consumeMotionEvent(
3085 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3086
3087 // Touch down on the right window
3088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3089 .deviceId(touchDeviceId)
3090 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3091 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003092 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003093 rightWindow->consumeMotionEvent(
3094 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003095
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003096 // Spy window does not receive touch events, because stylus events take precedence, and it
3097 // already has an active stylus gesture.
3098
3099 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003100 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3101 .deviceId(stylusDeviceId)
3102 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3103 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003104 leftWindow->consumeMotionEvent(
3105 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3106 spyWindow->consumeMotionEvent(
3107 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003108
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003109 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003110 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3111 .deviceId(touchDeviceId)
3112 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3113 .build());
3114 rightWindow->consumeMotionEvent(
3115 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003116
3117 spyWindow->assertNoEvents();
3118 leftWindow->assertNoEvents();
3119 rightWindow->assertNoEvents();
3120}
3121
3122/**
3123 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3124 * both.
3125 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003126 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003127 * At the same time, left and right should be getting independent streams of hovering and touch,
3128 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003129 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003130TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003131 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3132
3133 sp<FakeWindowHandle> spyWindow =
3134 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3135 spyWindow->setFrame(Rect(0, 0, 400, 400));
3136 spyWindow->setTrustedOverlay(true);
3137 spyWindow->setSpy(true);
3138
3139 sp<FakeWindowHandle> leftWindow =
3140 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3141 leftWindow->setFrame(Rect(0, 0, 200, 200));
3142
3143 sp<FakeWindowHandle> rightWindow =
3144 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3145 rightWindow->setFrame(Rect(200, 0, 400, 200));
3146
3147 mDispatcher->onWindowInfosChanged(
3148 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3149
3150 const int32_t stylusDeviceId = 1;
3151 const int32_t touchDeviceId = 2;
3152
3153 // Stylus hover on the left window
3154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3155 .deviceId(stylusDeviceId)
3156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3157 .build());
3158 leftWindow->consumeMotionEvent(
3159 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3160 spyWindow->consumeMotionEvent(
3161 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3162
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003163 // Touch down on the right window. Spy doesn't receive this touch because it already has
3164 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003165 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3166 .deviceId(touchDeviceId)
3167 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3168 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003169 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003170 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003171 rightWindow->consumeMotionEvent(
3172 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3173
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003174 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003175 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3176 .deviceId(stylusDeviceId)
3177 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3178 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003179 leftWindow->consumeMotionEvent(
3180 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003181 spyWindow->consumeMotionEvent(
3182 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003183
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003184 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003185 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3186 .deviceId(touchDeviceId)
3187 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3188 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003189 rightWindow->consumeMotionEvent(
3190 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3191
3192 spyWindow->assertNoEvents();
3193 leftWindow->assertNoEvents();
3194 rightWindow->assertNoEvents();
3195}
3196
3197/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003198 * On a single window, use two different devices: mouse and touch.
3199 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3200 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3201 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3202 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3203 * represent a new gesture.
3204 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003205TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003206 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3207 sp<FakeWindowHandle> window =
3208 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3209 window->setFrame(Rect(0, 0, 400, 400));
3210
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003211 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003212
3213 const int32_t touchDeviceId = 4;
3214 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003216 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003217 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3218 .deviceId(touchDeviceId)
3219 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3220 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003221 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003222 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3223 .deviceId(touchDeviceId)
3224 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3225 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003228 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3229 .deviceId(touchDeviceId)
3230 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3231 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3232 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003233 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3234 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3235 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3236
3237 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003238 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3239 .deviceId(mouseDeviceId)
3240 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3241 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3242 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003243
3244 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003245 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003246 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3247
Prabir Pradhan678438e2023-04-13 19:32:51 +00003248 mDispatcher->notifyMotion(
3249 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3250 .deviceId(mouseDeviceId)
3251 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3252 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3253 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3254 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003255 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3256
3257 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003258 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3259 .deviceId(touchDeviceId)
3260 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3261 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3262 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003263 // Since we already canceled this touch gesture, it will be ignored until a completely new
3264 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3265 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3266 // However, mouse movements should continue to work.
3267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3268 .deviceId(mouseDeviceId)
3269 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3270 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3271 .build());
3272 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3273
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003274 window->assertNoEvents();
3275}
3276
3277/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003278 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3279 * the injected event.
3280 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003281TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3283 sp<FakeWindowHandle> window =
3284 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3285 window->setFrame(Rect(0, 0, 400, 400));
3286
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003287 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003288
3289 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003290 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3291 // completion.
3292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003293 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003294 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3295 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003296 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003297 .build()));
3298 window->consumeMotionEvent(
3299 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3300
3301 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3302 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003303 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3304 .deviceId(touchDeviceId)
3305 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3306 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003307
3308 window->consumeMotionEvent(
3309 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3310 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3311}
3312
3313/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003314 * This test is similar to the test above, but the sequence of injected events is different.
3315 *
3316 * Two windows: a window on the left and a window on the right.
3317 * Mouse is hovered over the left window.
3318 * Next, we tap on the left window, where the cursor was last seen.
3319 *
3320 * After that, we inject one finger down onto the right window, and then a second finger down onto
3321 * the left window.
3322 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3323 * window (first), and then another on the left window (second).
3324 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3325 * In the buggy implementation, second finger down on the left window would cause a crash.
3326 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003327TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003328 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3329 sp<FakeWindowHandle> leftWindow =
3330 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3331 leftWindow->setFrame(Rect(0, 0, 200, 200));
3332
3333 sp<FakeWindowHandle> rightWindow =
3334 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3335 rightWindow->setFrame(Rect(200, 0, 400, 200));
3336
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003337 mDispatcher->onWindowInfosChanged(
3338 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003339
3340 const int32_t mouseDeviceId = 6;
3341 const int32_t touchDeviceId = 4;
3342 // Hover over the left window. Keep the cursor there.
3343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003344 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003345 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3346 AINPUT_SOURCE_MOUSE)
3347 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003348 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003349 .build()));
3350 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3351
3352 // Tap on left window
3353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003354 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003355 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3356 AINPUT_SOURCE_TOUCHSCREEN)
3357 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003358 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003359 .build()));
3360
3361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003362 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003363 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3364 AINPUT_SOURCE_TOUCHSCREEN)
3365 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003366 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003367 .build()));
3368 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3369 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3370 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3371
3372 // First finger down on right window
3373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003374 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003375 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3376 AINPUT_SOURCE_TOUCHSCREEN)
3377 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003378 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003379 .build()));
3380 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3381
3382 // Second finger down on the left window
3383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003384 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003385 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3386 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003387 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3388 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003389 .build()));
3390 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3391 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3392
3393 // No more events
3394 leftWindow->assertNoEvents();
3395 rightWindow->assertNoEvents();
3396}
3397
3398/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003399 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3400 * While the touch is down, new hover events from the stylus device should be ignored. After the
3401 * touch is gone, stylus hovering should start working again.
3402 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003403TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3405 sp<FakeWindowHandle> window =
3406 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3407 window->setFrame(Rect(0, 0, 200, 200));
3408
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410
3411 const int32_t stylusDeviceId = 5;
3412 const int32_t touchDeviceId = 4;
3413 // Start hovering with stylus
3414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003415 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003416 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003417 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003418 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003419 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003420 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003421
3422 // Finger down on the window
3423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003424 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003425 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003426 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003427 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003428 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003429 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003430
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003431 // Continue hovering with stylus.
3432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003433 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003434 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3435 AINPUT_SOURCE_STYLUS)
3436 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003437 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003438 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003439 // Hovers continue to work
3440 window->consumeMotionEvent(
3441 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003442
3443 // Lift up the finger
3444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003445 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003446 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3447 AINPUT_SOURCE_TOUCHSCREEN)
3448 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003449 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003450 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003451
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003453 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003454 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3455 AINPUT_SOURCE_STYLUS)
3456 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003457 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003458 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003459 window->consumeMotionEvent(
3460 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003461 window->assertNoEvents();
3462}
3463
3464/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003465 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3466 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3467 *
3468 * Two windows: one on the left and one on the right.
3469 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3470 * Stylus down on the left window, and then touch down on the right window.
3471 * Check that the right window doesn't get touches while the stylus is down on the left window.
3472 */
3473TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3475 sp<FakeWindowHandle> leftWindow =
3476 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3477 ADISPLAY_ID_DEFAULT);
3478 leftWindow->setFrame(Rect(0, 0, 100, 100));
3479
3480 sp<FakeWindowHandle> sbtRightWindow =
3481 sp<FakeWindowHandle>::make(application, mDispatcher,
3482 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3483 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3484 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3485
3486 mDispatcher->onWindowInfosChanged(
3487 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3488
3489 const int32_t stylusDeviceId = 5;
3490 const int32_t touchDeviceId = 4;
3491
3492 // Stylus down in the left window
3493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3494 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3495 .deviceId(stylusDeviceId)
3496 .build());
3497 leftWindow->consumeMotionEvent(
3498 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3499
3500 // Finger tap on the right window
3501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3502 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3503 .deviceId(touchDeviceId)
3504 .build());
3505 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3506 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3507 .deviceId(touchDeviceId)
3508 .build());
3509
3510 // The touch should be blocked, because stylus is down somewhere else on screen!
3511 sbtRightWindow->assertNoEvents();
3512
3513 // Continue stylus motion, and ensure it's not impacted.
3514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3515 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3516 .deviceId(stylusDeviceId)
3517 .build());
3518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3520 .deviceId(stylusDeviceId)
3521 .build());
3522 leftWindow->consumeMotionEvent(
3523 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3524 leftWindow->consumeMotionEvent(
3525 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3526
3527 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3528 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3529 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3530 .deviceId(touchDeviceId)
3531 .build());
3532 sbtRightWindow->consumeMotionEvent(
3533 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3534}
3535
3536/**
3537 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3538 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3539 *
3540 * Two windows: one on the left and one on the right.
3541 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3542 * Stylus hover on the left window, and then touch down on the right window.
3543 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3544 */
3545TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3547 sp<FakeWindowHandle> leftWindow =
3548 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3549 ADISPLAY_ID_DEFAULT);
3550 leftWindow->setFrame(Rect(0, 0, 100, 100));
3551
3552 sp<FakeWindowHandle> sbtRightWindow =
3553 sp<FakeWindowHandle>::make(application, mDispatcher,
3554 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3555 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3556 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3557
3558 mDispatcher->onWindowInfosChanged(
3559 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3560
3561 const int32_t stylusDeviceId = 5;
3562 const int32_t touchDeviceId = 4;
3563
3564 // Stylus hover in the left window
3565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3566 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3567 .deviceId(stylusDeviceId)
3568 .build());
3569 leftWindow->consumeMotionEvent(
3570 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3571
3572 // Finger tap on the right window
3573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3574 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3575 .deviceId(touchDeviceId)
3576 .build());
3577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3578 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3579 .deviceId(touchDeviceId)
3580 .build());
3581
3582 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3583 sbtRightWindow->assertNoEvents();
3584
3585 // Continue stylus motion, and ensure it's not impacted.
3586 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3587 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3588 .deviceId(stylusDeviceId)
3589 .build());
3590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3592 .deviceId(stylusDeviceId)
3593 .build());
3594 leftWindow->consumeMotionEvent(
3595 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3596 leftWindow->consumeMotionEvent(
3597 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3598
3599 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3601 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3602 .deviceId(touchDeviceId)
3603 .build());
3604 sbtRightWindow->consumeMotionEvent(
3605 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3606}
3607
3608/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003609 * A spy window above a window with no input channel.
3610 * Start hovering with a stylus device, and then tap with it.
3611 * Ensure spy window receives the entire sequence.
3612 */
3613TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3614 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3615 sp<FakeWindowHandle> spyWindow =
3616 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3617 spyWindow->setFrame(Rect(0, 0, 200, 200));
3618 spyWindow->setTrustedOverlay(true);
3619 spyWindow->setSpy(true);
3620 sp<FakeWindowHandle> window =
3621 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3622 window->setNoInputChannel(true);
3623 window->setFrame(Rect(0, 0, 200, 200));
3624
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003625 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003626
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003627 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003628 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3629 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3630 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003631 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3632 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3634 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3635 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003636 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3637
3638 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3640 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3641 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003642 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3643
3644 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3646 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3647 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003648 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3649
3650 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3652 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3653 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003654 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3655 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3657 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3658 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003659 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3660
3661 // No more events
3662 spyWindow->assertNoEvents();
3663 window->assertNoEvents();
3664}
3665
3666/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003667 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3668 * rejected. But since we already have an ongoing gesture, this event should be processed.
3669 * This prevents inconsistent events being handled inside the dispatcher.
3670 */
3671TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3673
3674 sp<FakeWindowHandle> window =
3675 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3676 window->setFrame(Rect(0, 0, 200, 200));
3677
3678 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3679
3680 // Start hovering with stylus
3681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3682 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3683 .build());
3684 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3685
3686 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3687 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3688 .build();
3689 // Make this 'hoverExit' event stale
3690 mFakePolicy->setStaleEventTimeout(100ms);
3691 std::this_thread::sleep_for(100ms);
3692
3693 // It shouldn't be dropped by the dispatcher, even though it's stale.
3694 mDispatcher->notifyMotion(hoverExit);
3695 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3696
3697 // Stylus starts hovering again! There should be no crash.
3698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3699 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3700 .build());
3701 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3702}
3703
3704/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003705 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3706 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3707 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3708 * While the mouse is down, new move events from the touch device should be ignored.
3709 */
3710TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3711 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3712 sp<FakeWindowHandle> spyWindow =
3713 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3714 spyWindow->setFrame(Rect(0, 0, 200, 200));
3715 spyWindow->setTrustedOverlay(true);
3716 spyWindow->setSpy(true);
3717 sp<FakeWindowHandle> window =
3718 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3719 window->setFrame(Rect(0, 0, 200, 200));
3720
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003721 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003722
3723 const int32_t mouseDeviceId = 7;
3724 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003725
3726 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3728 .deviceId(mouseDeviceId)
3729 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3730 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003731 spyWindow->consumeMotionEvent(
3732 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3733 window->consumeMotionEvent(
3734 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3735
3736 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3738 .deviceId(touchDeviceId)
3739 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3740 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003741 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3742 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3743 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3744 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3745
Prabir Pradhan678438e2023-04-13 19:32:51 +00003746 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3747 .deviceId(touchDeviceId)
3748 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3749 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003750 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3751 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3752
3753 // Pilfer the stream
3754 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3755 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3756
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3758 .deviceId(touchDeviceId)
3759 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3760 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003761 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3762
3763 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3765 .deviceId(mouseDeviceId)
3766 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3767 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3768 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003769
3770 spyWindow->consumeMotionEvent(
3771 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3772 spyWindow->consumeMotionEvent(
3773 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3774 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3775
Prabir Pradhan678438e2023-04-13 19:32:51 +00003776 mDispatcher->notifyMotion(
3777 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3778 .deviceId(mouseDeviceId)
3779 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3780 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3781 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3784 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3785
3786 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3788 .deviceId(mouseDeviceId)
3789 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3790 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3791 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003792 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3793 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3794
3795 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3797 .deviceId(touchDeviceId)
3798 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3799 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003800
3801 // No more events
3802 spyWindow->assertNoEvents();
3803 window->assertNoEvents();
3804}
3805
3806/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003807 * On the display, have a single window, and also an area where there's no window.
3808 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3809 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3810 */
3811TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3813 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003814 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003815
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003817
3818 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003819 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003820
3821 mDispatcher->waitForIdle();
3822 window->assertNoEvents();
3823
3824 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003825 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003826 mDispatcher->waitForIdle();
3827 window->consumeMotionDown();
3828}
3829
3830/**
3831 * Same test as above, but instead of touching the empty space, the first touch goes to
3832 * non-touchable window.
3833 */
3834TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3836 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003837 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003838 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3839 window1->setTouchable(false);
3840 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003841 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003842 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3843
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003844 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003845
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003846 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003847 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003848
3849 mDispatcher->waitForIdle();
3850 window1->assertNoEvents();
3851 window2->assertNoEvents();
3852
3853 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003854 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003855 mDispatcher->waitForIdle();
3856 window2->consumeMotionDown();
3857}
3858
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003859/**
3860 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3861 * to the event time of the first ACTION_DOWN sent to the particular window.
3862 */
3863TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3865 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003866 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3868 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003869 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003870 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3871
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003872 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003873
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003874 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003875 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003876 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003877
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003878 const std::unique_ptr<MotionEvent> firstDown =
3879 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3880 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003881 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003882
3883 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003884 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003885 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003886
3887 const std::unique_ptr<MotionEvent> secondDown =
3888 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3889 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3890 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3891 // We currently send MOVE events to all windows receiving a split touch when there is any change
3892 // in the touch state, even when none of the pointers in the split window actually moved.
3893 // Document this behavior in the test.
3894 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003895
3896 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003897 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003898 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003899
3900 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3901 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003902
3903 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003904 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003905 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003906
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003907 window2->consumeMotionEvent(
3908 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3909 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003910
3911 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003912 mDispatcher->notifyMotion(
3913 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003914 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003915
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003916 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3917 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3918
3919 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003920 mDispatcher->notifyMotion(
3921 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003922 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003923
3924 window1->consumeMotionEvent(
3925 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3926 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003927}
3928
Garfield Tandf26e862020-07-01 20:18:19 -07003929TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003931 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003932 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003933 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003934 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003935 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003936 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003937
3938 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3939
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003940 mDispatcher->onWindowInfosChanged(
3941 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003942
3943 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003945 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003946 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3947 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003949 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003950 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003951
3952 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003954 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003955 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3956 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003957 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003958 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003959 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3960 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003961
3962 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003964 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003965 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3966 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003968 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003969 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3970 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003971
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003972 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003973 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003974 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3975 AINPUT_SOURCE_MOUSE)
3976 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3977 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003978 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003979 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003980 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003981
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003983 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003984 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3985 AINPUT_SOURCE_MOUSE)
3986 .buttonState(0)
3987 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003988 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003989 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003990 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003991
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003993 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003994 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3995 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003996 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003997 .build()));
3998 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3999
4000 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004002 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004003 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4004 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004005 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004006 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004007 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004008
4009 // No more events
4010 windowLeft->assertNoEvents();
4011 windowRight->assertNoEvents();
4012}
4013
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004014/**
4015 * Put two fingers down (and don't release them) and click the mouse button.
4016 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4017 * currently active gesture should be canceled, and the new one should proceed.
4018 */
4019TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4021 sp<FakeWindowHandle> window =
4022 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4023 window->setFrame(Rect(0, 0, 600, 800));
4024
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004025 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004026
4027 const int32_t touchDeviceId = 4;
4028 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004029
4030 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004031 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4032 .deviceId(touchDeviceId)
4033 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4034 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004035
Prabir Pradhan678438e2023-04-13 19:32:51 +00004036 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4037 .deviceId(touchDeviceId)
4038 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4039 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4040 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004041 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4042 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4043
4044 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004045 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4046 .deviceId(mouseDeviceId)
4047 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4048 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4049 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004050 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4051 WithPointerCount(2u)));
4052 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4053
Prabir Pradhan678438e2023-04-13 19:32:51 +00004054 mDispatcher->notifyMotion(
4055 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4056 .deviceId(mouseDeviceId)
4057 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4058 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4059 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4060 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004061 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4062
4063 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4064 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004065 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4066 .deviceId(touchDeviceId)
4067 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4068 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4069 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004070 window->assertNoEvents();
4071}
4072
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004073TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4075
4076 sp<FakeWindowHandle> spyWindow =
4077 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4078 spyWindow->setFrame(Rect(0, 0, 600, 800));
4079 spyWindow->setTrustedOverlay(true);
4080 spyWindow->setSpy(true);
4081 sp<FakeWindowHandle> window =
4082 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4083 window->setFrame(Rect(0, 0, 600, 800));
4084
4085 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004086 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004087
4088 // Send mouse cursor to the window
4089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004090 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004091 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4092 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004093 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004094 .build()));
4095
4096 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4097 WithSource(AINPUT_SOURCE_MOUSE)));
4098 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4099 WithSource(AINPUT_SOURCE_MOUSE)));
4100
4101 window->assertNoEvents();
4102 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004103}
4104
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004105TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4106 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4107
4108 sp<FakeWindowHandle> spyWindow =
4109 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4110 spyWindow->setFrame(Rect(0, 0, 600, 800));
4111 spyWindow->setTrustedOverlay(true);
4112 spyWindow->setSpy(true);
4113 sp<FakeWindowHandle> window =
4114 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4115 window->setFrame(Rect(0, 0, 600, 800));
4116
4117 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004118 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004119
4120 // Send mouse cursor to the window
4121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004122 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004123 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4124 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004125 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004126 .build()));
4127
4128 // Move mouse cursor
4129 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004130 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004131 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4132 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004133 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004134 .build()));
4135
4136 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4137 WithSource(AINPUT_SOURCE_MOUSE)));
4138 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4139 WithSource(AINPUT_SOURCE_MOUSE)));
4140 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4141 WithSource(AINPUT_SOURCE_MOUSE)));
4142 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4143 WithSource(AINPUT_SOURCE_MOUSE)));
4144 // Touch down on the window
4145 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004146 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004147 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4148 AINPUT_SOURCE_TOUCHSCREEN)
4149 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004150 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004151 .build()));
4152 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4153 WithSource(AINPUT_SOURCE_MOUSE)));
4154 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4155 WithSource(AINPUT_SOURCE_MOUSE)));
4156 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4157 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4158 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4159 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4160
4161 // pilfer the motion, retaining the gesture on the spy window.
4162 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4163 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4164 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4165
4166 // Touch UP on the window
4167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004168 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004169 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4170 AINPUT_SOURCE_TOUCHSCREEN)
4171 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004172 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004173 .build()));
4174 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4175 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4176
4177 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4178 // to send a new gesture. It should again go to both windows (spy and the window below), just
4179 // like the first gesture did, before pilfering. The window configuration has not changed.
4180
4181 // One more tap - DOWN
4182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004183 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004184 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4185 AINPUT_SOURCE_TOUCHSCREEN)
4186 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004187 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004188 .build()));
4189 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4190 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4191 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4192 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4193
4194 // Touch UP on the window
4195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004196 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004197 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4198 AINPUT_SOURCE_TOUCHSCREEN)
4199 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004200 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004201 .build()));
4202 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4203 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4204 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4205 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4206
4207 window->assertNoEvents();
4208 spyWindow->assertNoEvents();
4209}
4210
Garfield Tandf26e862020-07-01 20:18:19 -07004211// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4212// directly in this test.
4213TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004214 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004215 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004216 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004217 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004218
4219 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4220
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004221 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004222
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004224 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004225 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4226 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004228 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004229 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004230 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004232 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004233 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4234 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004235 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004236 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004237 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4238 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004239
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004241 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004242 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4243 AINPUT_SOURCE_MOUSE)
4244 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4245 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004246 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004247 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004248 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004249
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004251 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004252 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4253 AINPUT_SOURCE_MOUSE)
4254 .buttonState(0)
4255 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004257 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004258 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004259
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004261 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004262 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4263 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004264 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004265 .build()));
4266 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4267
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004268 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4269 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4270 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004271 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004272 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4273 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004274 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004275 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004276 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004277}
4278
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004279/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004280 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4281 * is generated.
4282 */
4283TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4285 sp<FakeWindowHandle> window =
4286 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4287 window->setFrame(Rect(0, 0, 1200, 800));
4288
4289 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004292
4293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004294 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004295 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4296 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004297 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004298 .build()));
4299 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4300
4301 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004302 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004303 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4304}
4305
4306/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004307 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4308 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004309TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4310 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4311 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004312 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4313 sp<FakeWindowHandle> window =
4314 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4315 window->setFrame(Rect(0, 0, 1200, 800));
4316
4317 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4318
4319 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4320
4321 MotionEventBuilder hoverEnterBuilder =
4322 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4323 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4324 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4326 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4328 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4329 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4330 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4331}
4332
4333/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004334 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4335 */
4336TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4337 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4338 sp<FakeWindowHandle> window =
4339 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4340 window->setFrame(Rect(0, 0, 100, 100));
4341
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004342 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004343
4344 const int32_t mouseDeviceId = 7;
4345 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004346
4347 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4349 .deviceId(mouseDeviceId)
4350 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4351 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004352 window->consumeMotionEvent(
4353 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4354
4355 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4357 .deviceId(touchDeviceId)
4358 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4359 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004360
4361 window->consumeMotionEvent(
4362 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4363 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4364}
4365
4366/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004367 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004368 * The tap causes a HOVER_EXIT event to be generated because the current event
4369 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004370 */
4371TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4373 sp<FakeWindowHandle> window =
4374 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4375 window->setFrame(Rect(0, 0, 100, 100));
4376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004377 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004378 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4379 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4380 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004381 ASSERT_NO_FATAL_FAILURE(
4382 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4383 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004384
4385 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004386 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4388 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004389 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004390 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4391 WithSource(AINPUT_SOURCE_MOUSE))));
4392
4393 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004394 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4395 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4396
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4398 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4399 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004400 ASSERT_NO_FATAL_FAILURE(
4401 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4402 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4403}
4404
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004405TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4406 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4407 sp<FakeWindowHandle> windowDefaultDisplay =
4408 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4409 ADISPLAY_ID_DEFAULT);
4410 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4411 sp<FakeWindowHandle> windowSecondDisplay =
4412 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4413 SECOND_DISPLAY_ID);
4414 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4415
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004416 mDispatcher->onWindowInfosChanged(
4417 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004418
4419 // Set cursor position in window in default display and check that hover enter and move
4420 // events are generated.
4421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004422 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004423 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4424 AINPUT_SOURCE_MOUSE)
4425 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004426 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004427 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004428 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004429
4430 // Remove all windows in secondary display and check that no event happens on window in
4431 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004432 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4433
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004434 windowDefaultDisplay->assertNoEvents();
4435
4436 // Move cursor position in window in default display and check that only hover move
4437 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004438 mDispatcher->onWindowInfosChanged(
4439 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004441 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004442 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4443 AINPUT_SOURCE_MOUSE)
4444 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004445 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004446 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004447 windowDefaultDisplay->consumeMotionEvent(
4448 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4449 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004450 windowDefaultDisplay->assertNoEvents();
4451}
4452
Garfield Tan00f511d2019-06-12 16:55:40 -07004453TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004455
4456 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004457 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004458 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004459 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004460 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004461 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004462
4463 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4464
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004465 mDispatcher->onWindowInfosChanged(
4466 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004467
4468 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4469 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004471 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004472 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004473 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004474 windowRight->assertNoEvents();
4475}
4476
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004477TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004478 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004479 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4480 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004481 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004482
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004483 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004484 setFocusedWindow(window);
4485
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004486 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004487
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004489
4490 // Window should receive key down event.
4491 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4492
4493 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4494 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004495 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004496 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004497}
4498
4499TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004501 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4502 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004503
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004504 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004505
Prabir Pradhan678438e2023-04-13 19:32:51 +00004506 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4507 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004508
4509 // Window should receive motion down event.
4510 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4511
4512 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4513 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004514 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004515 window->consumeMotionEvent(
4516 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004517}
4518
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004519TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4521 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4522 "Fake Window", ADISPLAY_ID_DEFAULT);
4523
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004524 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004525
4526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4528 .build());
4529
4530 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4531
4532 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4533 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4534 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4535
4536 // After the device has been reset, a new hovering stream can be sent to the window
4537 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4538 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4539 .build());
4540 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4541}
4542
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004543TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4544 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004545 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4546 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004547 window->setFocusable(true);
4548
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004549 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004550 setFocusedWindow(window);
4551
4552 window->consumeFocusEvent(true);
4553
Prabir Pradhan678438e2023-04-13 19:32:51 +00004554 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004555 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4556 const nsecs_t injectTime = keyArgs.eventTime;
4557 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004558 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004559 // The dispatching time should be always greater than or equal to intercept key timeout.
4560 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4561 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4562 std::chrono::nanoseconds(interceptKeyTimeout).count());
4563}
4564
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004565/**
4566 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4567 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004568TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4569 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004570 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4571 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004572 window->setFocusable(true);
4573
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004574 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004575 setFocusedWindow(window);
4576
4577 window->consumeFocusEvent(true);
4578
Prabir Pradhan678438e2023-04-13 19:32:51 +00004579 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004580 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004581
4582 // Set a value that's significantly larger than the default consumption timeout. If the
4583 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4584 mFakePolicy->setInterceptKeyTimeout(600ms);
4585 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4586 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004587 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4588}
4589
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004590/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004591 * Two windows. First is a regular window. Second does not overlap with the first, and has
4592 * WATCH_OUTSIDE_TOUCH.
4593 * Both windows are owned by the same UID.
4594 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4595 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4596 */
4597TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004599 sp<FakeWindowHandle> window =
4600 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004601 window->setFrame(Rect{0, 0, 100, 100});
4602
4603 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004604 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004605 ADISPLAY_ID_DEFAULT);
4606 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4607 outsideWindow->setWatchOutsideTouch(true);
4608 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004609 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004610
4611 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004612 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4613 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4614 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004615 window->consumeMotionDown();
4616 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4617 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4618 outsideWindow->consumeMotionEvent(
4619 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004620
4621 // Ensure outsideWindow doesn't get any more events for the gesture.
4622 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4623 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4624 window->consumeMotionMove();
4625 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004626}
4627
4628/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004629 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4630 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4631 * ACTION_OUTSIDE event is sent per gesture.
4632 */
4633TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4634 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4635 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004636 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4637 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004638 window->setWatchOutsideTouch(true);
4639 window->setFrame(Rect{0, 0, 100, 100});
4640 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004641 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4642 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004643 secondWindow->setFrame(Rect{100, 100, 200, 200});
4644 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004645 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4646 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004647 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004648 mDispatcher->onWindowInfosChanged(
4649 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004650
4651 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004652 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4653 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4654 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004655 window->assertNoEvents();
4656 secondWindow->assertNoEvents();
4657
4658 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4659 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004660 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4661 ADISPLAY_ID_DEFAULT,
4662 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004663 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4664 window->consumeMotionEvent(
4665 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004666 secondWindow->consumeMotionDown();
4667 thirdWindow->assertNoEvents();
4668
4669 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4670 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004671 mDispatcher->notifyMotion(
4672 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4673 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004674 window->assertNoEvents();
4675 secondWindow->consumeMotionMove();
4676 thirdWindow->consumeMotionDown();
4677}
4678
Prabir Pradhan814fe082022-07-22 20:22:18 +00004679TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004681 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4682 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004683 window->setFocusable(true);
4684
Patrick Williamsd828f302023-04-28 17:52:08 -05004685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004686 setFocusedWindow(window);
4687
4688 window->consumeFocusEvent(true);
4689
Prabir Pradhan678438e2023-04-13 19:32:51 +00004690 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4691 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4692 mDispatcher->notifyKey(keyDown);
4693 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004694
4695 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4696 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4697
4698 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004699 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004700
4701 window->consumeFocusEvent(false);
4702
Prabir Pradhan678438e2023-04-13 19:32:51 +00004703 mDispatcher->notifyKey(keyDown);
4704 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004705 window->assertNoEvents();
4706}
4707
Arthur Hung96483742022-11-15 03:30:48 +00004708TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4710 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4711 "Fake Window", ADISPLAY_ID_DEFAULT);
4712 // Ensure window is non-split and have some transform.
4713 window->setPreventSplitting(true);
4714 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004715 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004716
4717 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004718 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004719 {50, 50}))
4720 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4721 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4722
4723 const MotionEvent secondFingerDownEvent =
4724 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4725 .displayId(ADISPLAY_ID_DEFAULT)
4726 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004727 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4728 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004729 .build();
4730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004731 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004732 InputEventInjectionSync::WAIT_FOR_RESULT))
4733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4734
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004735 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4736 ASSERT_NE(nullptr, event);
4737 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4738 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4739 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4740 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4741 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004742}
4743
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004744/**
4745 * Two windows: a splittable and a non-splittable.
4746 * The non-splittable window shouldn't receive any "incomplete" gestures.
4747 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4748 * The second pointer should be dropped because the initial window is splittable, so it won't get
4749 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4750 * "incomplete" gestures.
4751 */
4752TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4754 sp<FakeWindowHandle> leftWindow =
4755 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4756 ADISPLAY_ID_DEFAULT);
4757 leftWindow->setPreventSplitting(false);
4758 leftWindow->setFrame(Rect(0, 0, 100, 100));
4759 sp<FakeWindowHandle> rightWindow =
4760 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4761 ADISPLAY_ID_DEFAULT);
4762 rightWindow->setPreventSplitting(true);
4763 rightWindow->setFrame(Rect(100, 100, 200, 200));
4764 mDispatcher->onWindowInfosChanged(
4765 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4766
4767 // Touch down on left, splittable window
4768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4769 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4770 .build());
4771 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4772
4773 mDispatcher->notifyMotion(
4774 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4775 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4776 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4777 .build());
4778 leftWindow->assertNoEvents();
4779 rightWindow->assertNoEvents();
4780}
4781
Harry Cuttsb166c002023-05-09 13:06:05 +00004782TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4783 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4784 sp<FakeWindowHandle> window =
4785 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4786 window->setFrame(Rect(0, 0, 400, 400));
4787 sp<FakeWindowHandle> trustedOverlay =
4788 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4789 ADISPLAY_ID_DEFAULT);
4790 trustedOverlay->setSpy(true);
4791 trustedOverlay->setTrustedOverlay(true);
4792
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004793 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004794
4795 // Start a three-finger touchpad swipe
4796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4797 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4798 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4799 .build());
4800 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4801 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4802 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4803 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4804 .build());
4805 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4806 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4807 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4808 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4809 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4810 .build());
4811
4812 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4813 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4814 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4815
4816 // Move the swipe a bit
4817 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4818 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4819 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4820 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4821 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4822 .build());
4823
4824 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4825
4826 // End the swipe
4827 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4828 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4829 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4830 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4831 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4832 .build());
4833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4834 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4835 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4836 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4837 .build());
4838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4839 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4840 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4841 .build());
4842
4843 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4844 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4845 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4846
4847 window->assertNoEvents();
4848}
4849
4850TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4852 sp<FakeWindowHandle> window =
4853 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4854 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004856
4857 // Start a three-finger touchpad swipe
4858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4859 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4860 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4861 .build());
4862 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4863 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4864 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4865 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4866 .build());
4867 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4868 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4869 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4870 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4871 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4872 .build());
4873
4874 // Move the swipe a bit
4875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4876 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4877 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4878 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4879 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4880 .build());
4881
4882 // End the swipe
4883 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4884 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4885 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4886 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4887 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4888 .build());
4889 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4890 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4891 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4892 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4893 .build());
4894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4895 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4896 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4897 .build());
4898
4899 window->assertNoEvents();
4900}
4901
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004902/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004903 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4904 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004905 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004906 */
4907TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4909 sp<FakeWindowHandle> window =
4910 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4911 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004912 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004913
4914 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4916 .downTime(baseTime + 10)
4917 .eventTime(baseTime + 10)
4918 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4919 .build());
4920
4921 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4922
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004923 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004924 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004925
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004926 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004927
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004928 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4929 .downTime(baseTime + 10)
4930 .eventTime(baseTime + 30)
4931 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4932 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4933 .build());
4934
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004935 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4936
4937 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004938 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4939 .downTime(baseTime + 10)
4940 .eventTime(baseTime + 40)
4941 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4942 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4943 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004944
4945 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4946
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4948 .downTime(baseTime + 10)
4949 .eventTime(baseTime + 50)
4950 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4951 .build());
4952
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004953 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4954
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4956 .downTime(baseTime + 60)
4957 .eventTime(baseTime + 60)
4958 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4959 .build());
4960
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004961 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004962}
4963
4964/**
Hu Guo771a7692023-09-17 20:51:08 +08004965 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4966 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4967 * its coordinates should be converted by the transform of the windows of target screen.
4968 */
4969TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4970 // This case will create a window and a spy window on the default display and mirror
4971 // window on the second display. cancel event is sent through spy window pilferPointers
4972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4973
4974 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4975 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4976 spyWindowDefaultDisplay->setTrustedOverlay(true);
4977 spyWindowDefaultDisplay->setSpy(true);
4978
4979 sp<FakeWindowHandle> windowDefaultDisplay =
4980 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4981 ADISPLAY_ID_DEFAULT);
4982 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4983
4984 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4985 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4986
4987 // Add the windows to the dispatcher
4988 mDispatcher->onWindowInfosChanged(
4989 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4990 *windowSecondDisplay->getInfo()},
4991 {},
4992 0,
4993 0});
4994
4995 // Send down to ADISPLAY_ID_DEFAULT
4996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4997 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4998 {100, 100}))
4999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5000
5001 spyWindowDefaultDisplay->consumeMotionDown();
5002 windowDefaultDisplay->consumeMotionDown();
5003
5004 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5005
5006 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005007 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5008 ASSERT_NE(nullptr, event);
5009 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005010
5011 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
5012 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
5013 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
5014 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005015 EXPECT_EQ(100, event->getX(0));
5016 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005017}
5018
5019/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005020 * Ensure the correct coordinate spaces are used by InputDispatcher.
5021 *
5022 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5023 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5024 * space.
5025 */
5026class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5027public:
5028 void SetUp() override {
5029 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005030 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005031 }
5032
5033 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5034 gui::DisplayInfo info;
5035 info.displayId = displayId;
5036 info.transform = transform;
5037 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005038 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005039 }
5040
5041 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5042 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005043 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005044 }
5045
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005046 void removeAllWindowsAndDisplays() {
5047 mDisplayInfos.clear();
5048 mWindowInfos.clear();
5049 }
5050
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005051 // Set up a test scenario where the display has a scaled projection and there are two windows
5052 // on the display.
5053 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5054 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5055 // respectively.
5056 ui::Transform displayTransform;
5057 displayTransform.set(2, 0, 0, 4);
5058 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5059
5060 std::shared_ptr<FakeApplicationHandle> application =
5061 std::make_shared<FakeApplicationHandle>();
5062
5063 // Add two windows to the display. Their frames are represented in the display space.
5064 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005065 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5066 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005067 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5068 addWindow(firstWindow);
5069
5070 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005071 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5072 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005073 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5074 addWindow(secondWindow);
5075 return {std::move(firstWindow), std::move(secondWindow)};
5076 }
5077
5078private:
5079 std::vector<gui::DisplayInfo> mDisplayInfos;
5080 std::vector<gui::WindowInfo> mWindowInfos;
5081};
5082
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005083TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005084 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5085 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005086 // selected so that if the hit test was performed with the point and the bounds being in
5087 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005088 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5089 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5090 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005091
5092 firstWindow->consumeMotionDown();
5093 secondWindow->assertNoEvents();
5094}
5095
5096// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5097// the event should be treated as being in the logical display space.
5098TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5099 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5100 // Send down to the first window. The point is represented in the logical display space. The
5101 // point is selected so that if the hit test was done in logical display space, then it would
5102 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005103 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005104 PointF{75 * 2, 55 * 4});
5105
5106 firstWindow->consumeMotionDown();
5107 secondWindow->assertNoEvents();
5108}
5109
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005110// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5111// event should be treated as being in the logical display space.
5112TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5113 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5114
5115 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5116 ui::Transform injectedEventTransform;
5117 injectedEventTransform.set(matrix);
5118 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5119 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5120
5121 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5122 .displayId(ADISPLAY_ID_DEFAULT)
5123 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005124 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005125 .x(untransformedPoint.x)
5126 .y(untransformedPoint.y))
5127 .build();
5128 event.transform(matrix);
5129
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005130 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005131 InputEventInjectionSync::WAIT_FOR_RESULT);
5132
5133 firstWindow->consumeMotionDown();
5134 secondWindow->assertNoEvents();
5135}
5136
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005137TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5138 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5139
5140 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005141 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5142 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5143 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005144
5145 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005146 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5147 ASSERT_NE(nullptr, event);
5148 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005149
5150 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005151 EXPECT_EQ(300, event->getRawX(0));
5152 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005153
5154 // Ensure that the x and y values are in the window's coordinate space.
5155 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5156 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005157 EXPECT_EQ(100, event->getX(0));
5158 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005159}
5160
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005161TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5162 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5163 // The monitor will always receive events in the logical display's coordinate space, because
5164 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005165 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005166
5167 // Send down to the first window.
5168 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5169 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5170 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5171 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5172
5173 // Second pointer goes down on second window.
5174 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5175 ADISPLAY_ID_DEFAULT,
5176 {PointF{50, 100}, PointF{150, 220}}));
5177 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5178 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5179 {1, PointF{300, 880}}};
5180 monitor.consumeMotionEvent(
5181 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5182
5183 mDispatcher->cancelCurrentTouch();
5184
5185 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5186 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5187 monitor.consumeMotionEvent(
5188 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5189}
5190
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005191TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5192 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5193
5194 // Send down to the first window.
5195 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5196 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5197 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5198
5199 // The pointer is transferred to the second window, and the second window receives it in the
5200 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005201 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005202 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5203 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5204}
5205
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005206TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5207 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5208
5209 // Send hover move to the second window, and ensure it shows up as hover enter.
5210 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5211 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5212 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5213 WithCoords(100, 80), WithRawCoords(300, 880)));
5214
5215 // Touch down at the same location and ensure a hover exit is synthesized.
5216 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5217 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5218 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5219 WithRawCoords(300, 880)));
5220 secondWindow->consumeMotionEvent(
5221 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5222 secondWindow->assertNoEvents();
5223 firstWindow->assertNoEvents();
5224}
5225
Prabir Pradhan453ae732023-10-13 14:30:14 +00005226// Same as above, but while the window is being mirrored.
5227TEST_F(InputDispatcherDisplayProjectionTest,
5228 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5229 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5230
5231 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5232 ui::Transform secondDisplayTransform;
5233 secondDisplayTransform.set(matrix);
5234 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5235
5236 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5237 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5238 addWindow(secondWindowClone);
5239
5240 // Send hover move to the second window, and ensure it shows up as hover enter.
5241 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5242 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5243 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5244 WithCoords(100, 80), WithRawCoords(300, 880)));
5245
5246 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5247 // display.
5248 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5249 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5250 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5251 WithRawCoords(300, 880)));
5252 secondWindow->consumeMotionEvent(
5253 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5254 secondWindow->assertNoEvents();
5255 firstWindow->assertNoEvents();
5256}
5257
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005258TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5259 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5260
5261 // Send hover enter to second window
5262 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5263 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5264 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5265 WithCoords(100, 80), WithRawCoords(300, 880)));
5266
5267 mDispatcher->cancelCurrentTouch();
5268
5269 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5270 WithRawCoords(300, 880)));
5271 secondWindow->assertNoEvents();
5272 firstWindow->assertNoEvents();
5273}
5274
Prabir Pradhan453ae732023-10-13 14:30:14 +00005275// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005276TEST_F(InputDispatcherDisplayProjectionTest,
5277 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5278 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5279
5280 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5281 ui::Transform secondDisplayTransform;
5282 secondDisplayTransform.set(matrix);
5283 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5284
5285 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5286 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5287 addWindow(secondWindowClone);
5288
5289 // Send hover enter to second window
5290 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5291 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5292 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5293 WithCoords(100, 80), WithRawCoords(300, 880),
5294 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5295
5296 mDispatcher->cancelCurrentTouch();
5297
5298 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5299 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5300 WithRawCoords(300, 880),
5301 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5302 secondWindow->assertNoEvents();
5303 firstWindow->assertNoEvents();
5304}
5305
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005306/** Ensure consistent behavior of InputDispatcher in all orientations. */
5307class InputDispatcherDisplayOrientationFixture
5308 : public InputDispatcherDisplayProjectionTest,
5309 public ::testing::WithParamInterface<ui::Rotation> {};
5310
5311// This test verifies the touchable region of a window for all rotations of the display by tapping
5312// in different locations on the display, specifically points close to the four corners of a
5313// window.
5314TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5315 constexpr static int32_t displayWidth = 400;
5316 constexpr static int32_t displayHeight = 800;
5317
5318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5319
5320 const auto rotation = GetParam();
5321
5322 // Set up the display with the specified rotation.
5323 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5324 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5325 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5326 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5327 logicalDisplayWidth, logicalDisplayHeight);
5328 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5329
5330 // Create a window with its bounds determined in the logical display.
5331 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5332 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5333 sp<FakeWindowHandle> window =
5334 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5335 window->setFrame(frameInDisplay, displayTransform);
5336 addWindow(window);
5337
5338 // The following points in logical display space should be inside the window.
5339 static const std::array<vec2, 4> insidePoints{
5340 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5341 for (const auto pointInsideWindow : insidePoints) {
5342 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5343 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005344 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5345 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5346 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005347 window->consumeMotionDown();
5348
Prabir Pradhan678438e2023-04-13 19:32:51 +00005349 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5350 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5351 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005352 window->consumeMotionUp();
5353 }
5354
5355 // The following points in logical display space should be outside the window.
5356 static const std::array<vec2, 5> outsidePoints{
5357 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5358 for (const auto pointOutsideWindow : outsidePoints) {
5359 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5360 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005361 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5362 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5363 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005364
Prabir Pradhan678438e2023-04-13 19:32:51 +00005365 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5366 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5367 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005368 }
5369 window->assertNoEvents();
5370}
5371
5372// Run the precision tests for all rotations.
5373INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5374 InputDispatcherDisplayOrientationFixture,
5375 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5376 ui::ROTATION_270),
5377 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5378 return ftl::enum_string(testParamInfo.param);
5379 });
5380
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005381using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5382 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005383
5384class TransferTouchFixture : public InputDispatcherTest,
5385 public ::testing::WithParamInterface<TransferFunction> {};
5386
5387TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005389
5390 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005391 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005392 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5393 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005394 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005395 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005396 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5397 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005398 sp<FakeWindowHandle> wallpaper =
5399 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5400 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005401 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005402 mDispatcher->onWindowInfosChanged(
5403 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005404 setFocusedWindow(firstWindow);
5405 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005406
5407 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5409 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005410
Svet Ganov5d3bc372020-01-26 23:11:07 -08005411 // Only the first window should get the down event
5412 firstWindow->consumeMotionDown();
5413 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005414 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005415 // Dispatcher reports pointer down outside focus for the wallpaper
5416 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005417
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005418 // Transfer touch to the second window
5419 TransferFunction f = GetParam();
5420 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5421 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005422 // The first window gets cancel and the second gets down
5423 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005424 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005425 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005426 // There should not be any changes to the focused window when transferring touch
5427 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005428
5429 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005430 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5431 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005432 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005433 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005434 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005435 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005436}
5437
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005438/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005439 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5440 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5441 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005442 * natural to the user.
5443 * In this test, we are sending a pointer to both spy window and first window. We then try to
5444 * transfer touch to the second window. The dispatcher should identify the first window as the
5445 * one that should lose the gesture, and therefore the action should be to move the gesture from
5446 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005447 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5448 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005449 */
5450TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5451 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5452
5453 // Create a couple of windows + a spy window
5454 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005455 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005456 spyWindow->setTrustedOverlay(true);
5457 spyWindow->setSpy(true);
5458 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005459 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005460 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005461 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005462
5463 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005464 mDispatcher->onWindowInfosChanged(
5465 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005466
5467 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005468 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5469 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005470 // Only the first window and spy should get the down event
5471 spyWindow->consumeMotionDown();
5472 firstWindow->consumeMotionDown();
5473
5474 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005475 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005476 TransferFunction f = GetParam();
5477 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5478 ASSERT_TRUE(success);
5479 // The first window gets cancel and the second gets down
5480 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005481 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005482
5483 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005484 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5485 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005486 // The first window gets no events and the second+spy get up
5487 firstWindow->assertNoEvents();
5488 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005489 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005490}
5491
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005492TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005494
5495 PointF touchPoint = {10, 10};
5496
5497 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005498 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005499 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5500 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005501 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005502 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005503 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5504 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005505 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005506
5507 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005508 mDispatcher->onWindowInfosChanged(
5509 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005510
5511 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5513 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5514 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005515 // Only the first window should get the down event
5516 firstWindow->consumeMotionDown();
5517 secondWindow->assertNoEvents();
5518
5519 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005520 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5521 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005522 // Only the first window should get the pointer down event
5523 firstWindow->consumeMotionPointerDown(1);
5524 secondWindow->assertNoEvents();
5525
5526 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005527 TransferFunction f = GetParam();
5528 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5529 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005530 // The first window gets cancel and the second gets down and pointer down
5531 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005532 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5533 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5534 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005535
5536 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005537 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5538 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005539 // The first window gets nothing and the second gets pointer up
5540 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005541 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5542 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005543
5544 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005545 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5546 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005547 // The first window gets nothing and the second gets up
5548 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005549 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005550}
5551
Arthur Hungc539dbb2022-12-08 07:45:36 +00005552TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5554
5555 // Create a couple of windows
5556 sp<FakeWindowHandle> firstWindow =
5557 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5558 ADISPLAY_ID_DEFAULT);
5559 firstWindow->setDupTouchToWallpaper(true);
5560 sp<FakeWindowHandle> secondWindow =
5561 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5562 ADISPLAY_ID_DEFAULT);
5563 secondWindow->setDupTouchToWallpaper(true);
5564
5565 sp<FakeWindowHandle> wallpaper1 =
5566 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5567 wallpaper1->setIsWallpaper(true);
5568
5569 sp<FakeWindowHandle> wallpaper2 =
5570 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5571 wallpaper2->setIsWallpaper(true);
5572 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005573 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5574 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5575 {},
5576 0,
5577 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005578
5579 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005580 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5581 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005582
5583 // Only the first window should get the down event
5584 firstWindow->consumeMotionDown();
5585 secondWindow->assertNoEvents();
5586 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5587 wallpaper2->assertNoEvents();
5588
5589 // Transfer touch focus to the second window
5590 TransferFunction f = GetParam();
5591 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5592 ASSERT_TRUE(success);
5593
5594 // The first window gets cancel and the second gets down
5595 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005596 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005597 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005598 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5599 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005600
5601 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005602 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5603 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005604 // The first window gets no events and the second gets up
5605 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005606 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005607 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005608 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5609 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005610}
5611
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005612// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005613// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005614// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005615INSTANTIATE_TEST_SUITE_P(
5616 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5617 ::testing::Values(
5618 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5619 sp<IBinder> destChannelToken) {
5620 return dispatcher->transferTouchOnDisplay(destChannelToken,
5621 ADISPLAY_ID_DEFAULT);
5622 },
5623 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5624 sp<IBinder> to) {
5625 return dispatcher->transferTouchGesture(from, to,
5626 /*isDragAndDrop=*/false);
5627 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005628
Prabir Pradhan367f3432024-02-13 23:05:58 +00005629TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005631
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005632 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005633 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5634 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005635 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005636
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005637 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005638 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5639 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005640 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005641
5642 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005643 mDispatcher->onWindowInfosChanged(
5644 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005645
5646 PointF pointInFirst = {300, 200};
5647 PointF pointInSecond = {300, 600};
5648
5649 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005650 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5651 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5652 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005653 // Only the first window should get the down event
5654 firstWindow->consumeMotionDown();
5655 secondWindow->assertNoEvents();
5656
5657 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005658 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5659 ADISPLAY_ID_DEFAULT,
5660 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005661 // The first window gets a move and the second a down
5662 firstWindow->consumeMotionMove();
5663 secondWindow->consumeMotionDown();
5664
Prabir Pradhan367f3432024-02-13 23:05:58 +00005665 // Transfer touch to the second window
5666 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005667 // The first window gets cancel and the new gets pointer down (it already saw down)
5668 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005669 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5670 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005671
5672 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005673 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5674 ADISPLAY_ID_DEFAULT,
5675 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005676 // The first window gets nothing and the second gets pointer up
5677 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005678 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5679 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005680
5681 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005682 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5683 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005684 // The first window gets nothing and the second gets up
5685 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005686 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005687}
5688
Prabir Pradhan367f3432024-02-13 23:05:58 +00005689// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5690// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5691// receiving touch is not supported, so the touch should continue on those windows and the
5692// transferred-to window should get nothing.
5693TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5695
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005696 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005697 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5698 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005699 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005700
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005701 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005702 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5703 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005704 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005705
5706 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005707 mDispatcher->onWindowInfosChanged(
5708 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005709
5710 PointF pointInFirst = {300, 200};
5711 PointF pointInSecond = {300, 600};
5712
5713 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005714 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5715 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5716 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005717 // Only the first window should get the down event
5718 firstWindow->consumeMotionDown();
5719 secondWindow->assertNoEvents();
5720
5721 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005722 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5723 ADISPLAY_ID_DEFAULT,
5724 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005725 // The first window gets a move and the second a down
5726 firstWindow->consumeMotionMove();
5727 secondWindow->consumeMotionDown();
5728
5729 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005730 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005731 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5732 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005733 ASSERT_FALSE(transferred);
5734 firstWindow->assertNoEvents();
5735 secondWindow->assertNoEvents();
5736
5737 // The rest of the dispatch should proceed as normal
5738 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005739 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5740 ADISPLAY_ID_DEFAULT,
5741 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005742 // The first window gets MOVE and the second gets pointer up
5743 firstWindow->consumeMotionMove();
5744 secondWindow->consumeMotionUp();
5745
5746 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005747 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5748 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005749 // The first window gets nothing and the second gets up
5750 firstWindow->consumeMotionUp();
5751 secondWindow->assertNoEvents();
5752}
5753
Arthur Hungabbb9d82021-09-01 14:52:30 +00005754// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005755// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005756// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005757TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005758 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5759 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005760 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005761 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005762 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005763 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005764 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005765
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005766 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005767 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005768
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005769 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005770 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005771
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005772 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005773 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005774
5775 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005776 mDispatcher->onWindowInfosChanged(
5777 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5778 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5779 *secondWindowInPrimary->getInfo()},
5780 {},
5781 0,
5782 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005783
5784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005785 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005786 {50, 50}))
5787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5788
5789 // Window should receive motion event.
5790 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5791
Prabir Pradhan367f3432024-02-13 23:05:58 +00005792 // Transfer touch
5793 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5794 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005795 // The first window gets cancel.
5796 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005797 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5798 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005799
5800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005801 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005802 ADISPLAY_ID_DEFAULT, {150, 50}))
5803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5804 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005805 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5806 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005807
5808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005809 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005810 {150, 50}))
5811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5812 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005813 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005814}
5815
Prabir Pradhan367f3432024-02-13 23:05:58 +00005816// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5817// 'transferTouchOnDisplay' api.
5818TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5820 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005821 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005822 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005823 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005824 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005825 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005826
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005827 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005828 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005829
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005830 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005831 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005832
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005833 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005834 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005835
5836 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005837 mDispatcher->onWindowInfosChanged(
5838 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5839 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5840 *secondWindowInPrimary->getInfo()},
5841 {},
5842 0,
5843 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005844
5845 // Touch on second display.
5846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005847 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5848 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005849 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5850
5851 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005852 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005853
5854 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005855 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5856 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005857
5858 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005859 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005860 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5861 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005862
5863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005864 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005865 SECOND_DISPLAY_ID, {150, 50}))
5866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005867 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005868 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5869 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005870
5871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005872 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005874 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005875 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005876}
5877
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005878TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005880 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5881 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005882
Vishnu Nair47074b82020-08-14 11:54:47 -07005883 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005884 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005885 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005886
5887 window->consumeFocusEvent(true);
5888
Prabir Pradhan678438e2023-04-13 19:32:51 +00005889 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005890
5891 // Window should receive key down event.
5892 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005893
5894 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005895 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005896 mFakePolicy->assertUserActivityPoked();
5897}
5898
5899TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5901 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5902 "Fake Window", ADISPLAY_ID_DEFAULT);
5903
5904 window->setDisableUserActivity(true);
5905 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005907 setFocusedWindow(window);
5908
5909 window->consumeFocusEvent(true);
5910
5911 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5912
5913 // Window should receive key down event.
5914 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5915
5916 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005917 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005918 mFakePolicy->assertUserActivityNotPoked();
5919}
5920
5921TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5923 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5924 "Fake Window", ADISPLAY_ID_DEFAULT);
5925
5926 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005927 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005928 setFocusedWindow(window);
5929
5930 window->consumeFocusEvent(true);
5931
5932 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5933 mDispatcher->waitForIdle();
5934
5935 // System key is not passed down
5936 window->assertNoEvents();
5937
5938 // Should have poked user activity
5939 mFakePolicy->assertUserActivityPoked();
5940}
5941
5942TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5944 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5945 "Fake Window", ADISPLAY_ID_DEFAULT);
5946
5947 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005948 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005949 setFocusedWindow(window);
5950
5951 window->consumeFocusEvent(true);
5952
5953 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5954 mDispatcher->waitForIdle();
5955
5956 // System key is not passed down
5957 window->assertNoEvents();
5958
5959 // Should have poked user activity
5960 mFakePolicy->assertUserActivityPoked();
5961}
5962
5963TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5964 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5965 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5966 "Fake Window", ADISPLAY_ID_DEFAULT);
5967
5968 window->setDisableUserActivity(true);
5969 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005970 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005971 setFocusedWindow(window);
5972
5973 window->consumeFocusEvent(true);
5974
5975 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5976 mDispatcher->waitForIdle();
5977
5978 // System key is not passed down
5979 window->assertNoEvents();
5980
5981 // Should have poked user activity
5982 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005983}
5984
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005985TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5987 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5988 "Fake Window", ADISPLAY_ID_DEFAULT);
5989
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005990 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005991
5992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005993 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005994 ADISPLAY_ID_DEFAULT, {100, 100}))
5995 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5996
5997 window->consumeMotionEvent(
5998 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5999
6000 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006001 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006002 mFakePolicy->assertUserActivityPoked();
6003}
6004
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006005TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006006 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006007 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6008 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006009
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006010 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006011
Prabir Pradhan678438e2023-04-13 19:32:51 +00006012 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006013 mDispatcher->waitForIdle();
6014
6015 window->assertNoEvents();
6016}
6017
6018// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6019TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6022 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006023
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006025
6026 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006027 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006028 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006029 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6030 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006031
6032 // Window should receive only the motion event
6033 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6034 window->assertNoEvents(); // Key event or focus event will not be received
6035}
6036
arthurhungea3f4fc2020-12-21 23:18:53 +08006037TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6038 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6039
arthurhungea3f4fc2020-12-21 23:18:53 +08006040 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006041 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6042 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006043 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006044
arthurhungea3f4fc2020-12-21 23:18:53 +08006045 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006046 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6047 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006048 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006049
6050 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006051 mDispatcher->onWindowInfosChanged(
6052 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006053
6054 PointF pointInFirst = {300, 200};
6055 PointF pointInSecond = {300, 600};
6056
6057 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006058 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6059 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6060 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006061 // Only the first window should get the down event
6062 firstWindow->consumeMotionDown();
6063 secondWindow->assertNoEvents();
6064
6065 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006066 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6067 ADISPLAY_ID_DEFAULT,
6068 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006069 // The first window gets a move and the second a down
6070 firstWindow->consumeMotionMove();
6071 secondWindow->consumeMotionDown();
6072
6073 // Send pointer cancel to the second window
6074 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006075 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006076 {pointInFirst, pointInSecond});
6077 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006078 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006079 // The first window gets move and the second gets cancel.
6080 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6081 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6082
6083 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006084 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6085 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006086 // The first window gets up and the second gets nothing.
6087 firstWindow->consumeMotionUp();
6088 secondWindow->assertNoEvents();
6089}
6090
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006091TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6093
6094 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006095 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006097 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6098 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6099 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6100
Harry Cutts33476232023-01-30 19:57:29 +00006101 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006102 window->assertNoEvents();
6103 mDispatcher->waitForIdle();
6104}
6105
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006106using InputDispatcherMonitorTest = InputDispatcherTest;
6107
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006108/**
6109 * Two entities that receive touch: A window, and a global monitor.
6110 * The touch goes to the window, and then the window disappears.
6111 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6112 * for the monitor, as well.
6113 * 1. foregroundWindow
6114 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6115 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006116TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006117 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6118 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006119 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006120
Prabir Pradhanfb549072023-10-05 19:17:36 +00006121 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006122
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006123 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006125 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006126 {100, 200}))
6127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6128
6129 // Both the foreground window and the global monitor should receive the touch down
6130 window->consumeMotionDown();
6131 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6132
6133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006134 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006135 ADISPLAY_ID_DEFAULT, {110, 200}))
6136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6137
6138 window->consumeMotionMove();
6139 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6140
6141 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006142 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006143 window->consumeMotionCancel();
6144 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6145
6146 // If more events come in, there will be no more foreground window to send them to. This will
6147 // cause a cancel for the monitor, as well.
6148 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006149 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006150 ADISPLAY_ID_DEFAULT, {120, 200}))
6151 << "Injection should fail because the window was removed";
6152 window->assertNoEvents();
6153 // Global monitor now gets the cancel
6154 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6155}
6156
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006157TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006158 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006159 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6160 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006161 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006162
Prabir Pradhanfb549072023-10-05 19:17:36 +00006163 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006164
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006166 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006168 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006169 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006170}
6171
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006172TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006173 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006174
Chris Yea209fde2020-07-22 13:54:51 -07006175 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006176 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6177 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006178 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006179
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006181 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006182 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006183 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006184 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006185
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006186 // Pilfer pointers from the monitor.
6187 // This should not do anything and the window should continue to receive events.
6188 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006189
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006190 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006191 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006192 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006193 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006194
6195 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6196 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006197}
6198
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006199TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006200 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006201 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6202 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006203 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006204 window->setWindowOffset(20, 40);
6205 window->setWindowTransform(0, 1, -1, 0);
6206
Prabir Pradhanfb549072023-10-05 19:17:36 +00006207 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006208
6209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006210 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006211 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6212 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006213 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6214 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006215 // Even though window has transform, gesture monitor must not.
6216 ASSERT_EQ(ui::Transform(), event->getTransform());
6217}
6218
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006219TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006221 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006222
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006223 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006225 << "Injection should fail if there is a monitor, but no touchable window";
6226 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006227}
6228
Linnan Lid8150952024-01-26 18:07:17 +00006229/**
6230 * Two displays
6231 * The first monitor has a foreground window, a monitor
6232 * The second window has only one monitor.
6233 * We first inject a Down event into the first display, this injection should succeed and both
6234 * the foreground window and monitor should receive a down event, then inject a Down event into
6235 * the second display as well, this injection should fail, at this point, the first display
6236 * window and monitor should not receive a cancel or any other event.
6237 * Continue to inject Move and UP events to the first display, the events should be received
6238 * normally by the foreground window and monitor.
6239 */
6240TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6241 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6242 sp<FakeWindowHandle> window =
6243 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6244
6245 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6246 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6247
6248 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6250 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6251 {100, 200}))
6252 << "The down event injected into the first display should succeed";
6253
6254 window->consumeMotionDown();
6255 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006256
6257 ASSERT_EQ(InputEventInjectionResult::FAILED,
6258 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6259 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006260 << "The down event injected into the second display should fail since there's no "
6261 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006262
6263 // Continue to inject event to first display.
6264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6265 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6266 ADISPLAY_ID_DEFAULT, {110, 220}))
6267 << "The move event injected into the first display should succeed";
6268
6269 window->consumeMotionMove();
6270 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006271
6272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6273 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6274 {110, 220}))
6275 << "The up event injected into the first display should succeed";
6276
6277 window->consumeMotionUp();
6278 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006279
6280 window->assertNoEvents();
6281 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006282 secondMonitor.assertNoEvents();
6283}
6284
6285/**
6286 * Two displays
6287 * There is a monitor and foreground window on each display.
6288 * First, we inject down events into each of the two displays, at this point, the foreground windows
6289 * and monitors on both displays should receive down events.
6290 * At this point, the foreground window of the second display goes away, the gone window should
6291 * receive the cancel event, and the other windows and monitors should not receive any events.
6292 * Inject a move event into the second display. At this point, the injection should fail because
6293 * the second display no longer has a foreground window. At this point, the monitor on the second
6294 * display should receive a cancel event, and any windows or monitors on the first display should
6295 * not receive any events, and any subsequent injection of events into the second display should
6296 * also fail.
6297 * Continue to inject events into the first display, and the events should all be injected
6298 * successfully and received normally.
6299 */
6300TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6302 sp<FakeWindowHandle> window =
6303 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6304 sp<FakeWindowHandle> secondWindow =
6305 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6306 SECOND_DISPLAY_ID);
6307
6308 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6309 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6310
6311 // There is a foreground window on both displays.
6312 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6314 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6315 {100, 200}))
6316 << "The down event injected into the first display should succeed";
6317
6318 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6319 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006320
6321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6322 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6323 {100, 200}))
6324 << "The down event injected into the second display should succeed";
6325
Linnan Lid8150952024-01-26 18:07:17 +00006326 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6327 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6328
6329 // Now second window is gone away.
6330 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6331
6332 // The gone window should receive a cancel, and the monitor on the second display should not
6333 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006334 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6335 secondMonitor.assertNoEvents();
6336
6337 ASSERT_EQ(InputEventInjectionResult::FAILED,
6338 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6339 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006340 << "The move event injected into the second display should fail because there's no "
6341 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006342 // Now the monitor on the second display should receive a cancel event.
6343 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006344
6345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6346 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6347 ADISPLAY_ID_DEFAULT, {110, 200}))
6348 << "The move event injected into the first display should succeed";
6349
6350 window->consumeMotionMove();
6351 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006352
6353 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006354 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6355 {110, 220}))
6356 << "The up event injected into the second display should fail because there's no "
6357 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006358
6359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6360 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6361 {110, 220}))
6362 << "The up event injected into the first display should succeed";
6363
6364 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6365 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006366
Linnan Lid8150952024-01-26 18:07:17 +00006367 window->assertNoEvents();
6368 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006369 secondWindow->assertNoEvents();
6370 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006371}
6372
6373/**
6374 * One display with transform
6375 * There is a foreground window and a monitor on the display
6376 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6377 * event and move event, then let the foreground window go away, the foreground window receives
6378 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6379 * by the monitor should be with the same transform as the display
6380 */
6381TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6383 sp<FakeWindowHandle> window =
6384 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6385 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6386
6387 ui::Transform transform;
6388 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6389
6390 gui::DisplayInfo displayInfo;
6391 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6392 displayInfo.transform = transform;
6393
6394 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6395
6396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6397 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6398 {100, 200}))
6399 << "The down event injected should succeed";
6400
6401 window->consumeMotionDown();
6402 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6403 EXPECT_EQ(transform, downMotionEvent->getTransform());
6404 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6405
6406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6407 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6408 ADISPLAY_ID_DEFAULT, {110, 220}))
6409 << "The move event injected should succeed";
6410
6411 window->consumeMotionMove();
6412 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6413 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6414 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6415
6416 // Let foreground window gone
6417 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6418
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006419 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006420 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006421
6422 ASSERT_EQ(InputEventInjectionResult::FAILED,
6423 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6424 ADISPLAY_ID_DEFAULT, {110, 220}))
6425 << "The move event injected should failed";
6426 // Now foreground should not receive any events, but monitor should receive a cancel event
6427 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006428 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6429 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6430 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6431 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6432
6433 // Other event inject to this display should fail.
6434 ASSERT_EQ(InputEventInjectionResult::FAILED,
6435 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6436 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006437 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006438 window->assertNoEvents();
6439 monitor.assertNoEvents();
6440}
6441
chaviw81e2bb92019-12-18 15:03:51 -08006442TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006443 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006444 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6445 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006448
6449 NotifyMotionArgs motionArgs =
6450 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6451 ADISPLAY_ID_DEFAULT);
6452
Prabir Pradhan678438e2023-04-13 19:32:51 +00006453 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006454 // Window should receive motion down event.
6455 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6456
6457 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006458 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006459 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6460 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6461 motionArgs.pointerCoords[0].getX() - 10);
6462
Prabir Pradhan678438e2023-04-13 19:32:51 +00006463 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006464 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006465}
6466
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006467/**
6468 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6469 * the device default right away. In the test scenario, we check both the default value,
6470 * and the action of enabling / disabling.
6471 */
6472TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006474 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6475 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006476 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006477
6478 // Set focused application.
6479 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006480 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006481
6482 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006483 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006484 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006485 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006486
6487 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006488 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006489 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006490 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006491
6492 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006493 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006494 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006495 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006496 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006498 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006499 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006500
6501 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006502 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006503 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006504 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006505
6506 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006507 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006508 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006509 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006510 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006511 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006512 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006513 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006514
6515 window->assertNoEvents();
6516}
6517
Gang Wange9087892020-01-07 12:17:14 -05006518TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006519 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006520 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6521 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006522
6523 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006524 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006525
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006526 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006527 setFocusedWindow(window);
6528
Harry Cutts33476232023-01-30 19:57:29 +00006529 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006530
Prabir Pradhan678438e2023-04-13 19:32:51 +00006531 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6532 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006533
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006534 std::unique_ptr<KeyEvent> event = window->consumeKey();
6535 ASSERT_NE(event, nullptr);
6536 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006537 ASSERT_NE(verified, nullptr);
6538 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6539
6540 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6541 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6542 ASSERT_EQ(keyArgs.source, verified->source);
6543 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6544
6545 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6546
6547 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006548 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006549 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006550 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6551 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6552 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6553 ASSERT_EQ(0, verifiedKey.repeatCount);
6554}
6555
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006556TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006558 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6559 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006560
6561 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6562
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006563 ui::Transform transform;
6564 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6565
6566 gui::DisplayInfo displayInfo;
6567 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6568 displayInfo.transform = transform;
6569
Patrick Williamsd828f302023-04-28 17:52:08 -05006570 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006571
Prabir Pradhan678438e2023-04-13 19:32:51 +00006572 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006573 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6574 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006575 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006576
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006577 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6578 ASSERT_NE(nullptr, event);
6579 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006580 ASSERT_NE(verified, nullptr);
6581 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6582
6583 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6584 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6585 EXPECT_EQ(motionArgs.source, verified->source);
6586 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6587
6588 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6589
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006590 const vec2 rawXY =
6591 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6592 motionArgs.pointerCoords[0].getXYValue());
6593 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6594 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006595 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006596 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006597 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006598 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6599 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6600}
6601
chaviw09c8d2d2020-08-24 15:48:26 -07006602/**
6603 * Ensure that separate calls to sign the same data are generating the same key.
6604 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6605 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6606 * tests.
6607 */
6608TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6609 KeyEvent event = getTestKeyEvent();
6610 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6611
6612 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6613 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6614 ASSERT_EQ(hmac1, hmac2);
6615}
6616
6617/**
6618 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6619 */
6620TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6621 KeyEvent event = getTestKeyEvent();
6622 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6623 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6624
6625 verifiedEvent.deviceId += 1;
6626 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6627
6628 verifiedEvent.source += 1;
6629 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6630
6631 verifiedEvent.eventTimeNanos += 1;
6632 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6633
6634 verifiedEvent.displayId += 1;
6635 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6636
6637 verifiedEvent.action += 1;
6638 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6639
6640 verifiedEvent.downTimeNanos += 1;
6641 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6642
6643 verifiedEvent.flags += 1;
6644 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6645
6646 verifiedEvent.keyCode += 1;
6647 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6648
6649 verifiedEvent.scanCode += 1;
6650 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6651
6652 verifiedEvent.metaState += 1;
6653 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6654
6655 verifiedEvent.repeatCount += 1;
6656 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6657}
6658
Vishnu Nair958da932020-08-21 17:12:37 -07006659TEST_F(InputDispatcherTest, SetFocusedWindow) {
6660 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6661 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006662 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006663 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006664 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006665 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6666
6667 // Top window is also focusable but is not granted focus.
6668 windowTop->setFocusable(true);
6669 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006670 mDispatcher->onWindowInfosChanged(
6671 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006672 setFocusedWindow(windowSecond);
6673
6674 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006677
6678 // Focused window should receive event.
6679 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6680 windowTop->assertNoEvents();
6681}
6682
6683TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6685 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006686 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006687 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6688
6689 window->setFocusable(true);
6690 // Release channel for window is no longer valid.
6691 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006693 setFocusedWindow(window);
6694
6695 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006696 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006697
6698 // window channel is invalid, so it should not receive any input event.
6699 window->assertNoEvents();
6700}
6701
6702TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6704 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006705 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006706 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006707 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006710 setFocusedWindow(window);
6711
6712 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006713 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006714
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006715 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006716 window->assertNoEvents();
6717}
6718
6719TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6721 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006722 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006723 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006724 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006725 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6726
6727 windowTop->setFocusable(true);
6728 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006729 mDispatcher->onWindowInfosChanged(
6730 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006731 setFocusedWindow(windowTop);
6732 windowTop->consumeFocusEvent(true);
6733
Chavi Weingarten847e8512023-03-29 00:26:09 +00006734 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006735 mDispatcher->onWindowInfosChanged(
6736 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006737 windowSecond->consumeFocusEvent(true);
6738 windowTop->consumeFocusEvent(false);
6739
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006741 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006742
6743 // Focused window should receive event.
6744 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6745}
6746
Chavi Weingarten847e8512023-03-29 00:26:09 +00006747TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6749 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006750 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006751 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006752 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006753 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6754
6755 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006756 windowSecond->setFocusable(false);
6757 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006758 mDispatcher->onWindowInfosChanged(
6759 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006760 setFocusedWindow(windowTop);
6761 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006762
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006764 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006765
6766 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006767 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006768 windowSecond->assertNoEvents();
6769}
6770
6771TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6773 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006774 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006775 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006776 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6777 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006778 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6779
6780 window->setFocusable(true);
6781 previousFocusedWindow->setFocusable(true);
6782 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006783 mDispatcher->onWindowInfosChanged(
6784 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006785 setFocusedWindow(previousFocusedWindow);
6786 previousFocusedWindow->consumeFocusEvent(true);
6787
6788 // Requesting focus on invisible window takes focus from currently focused window.
6789 setFocusedWindow(window);
6790 previousFocusedWindow->consumeFocusEvent(false);
6791
6792 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006794 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6795 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006796
6797 // Window does not get focus event or key down.
6798 window->assertNoEvents();
6799
6800 // Window becomes visible.
6801 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006802 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006803
6804 // Window receives focus event.
6805 window->consumeFocusEvent(true);
6806 // Focused window receives key down.
6807 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6808}
6809
Vishnu Nair599f1412021-06-21 10:39:58 -07006810TEST_F(InputDispatcherTest, DisplayRemoved) {
6811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6812 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006813 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006814 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6815
6816 // window is granted focus.
6817 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006818 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006819 setFocusedWindow(window);
6820 window->consumeFocusEvent(true);
6821
6822 // When a display is removed window loses focus.
6823 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6824 window->consumeFocusEvent(false);
6825}
6826
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006827/**
6828 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6829 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6830 * of the 'slipperyEnterWindow'.
6831 *
6832 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6833 * a way so that the touched location is no longer covered by the top window.
6834 *
6835 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6836 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6837 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6838 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6839 * with ACTION_DOWN).
6840 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6841 * window moved itself away from the touched location and had Flag::SLIPPERY.
6842 *
6843 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6844 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6845 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6846 *
6847 * In this test, we ensure that the event received by the bottom window has
6848 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6849 */
6850TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006851 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006852 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006853
6854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6855 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6856
6857 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006858 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006859 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006860 // Make sure this one overlaps the bottom window
6861 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6862 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6863 // one. Windows with the same owner are not considered to be occluding each other.
6864 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6865
6866 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006867 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006868 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6869
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006870 mDispatcher->onWindowInfosChanged(
6871 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006872
6873 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006874 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6875 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6876 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006877 slipperyExitWindow->consumeMotionDown();
6878 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006879 mDispatcher->onWindowInfosChanged(
6880 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006881
Prabir Pradhan678438e2023-04-13 19:32:51 +00006882 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6883 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6884 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006885
6886 slipperyExitWindow->consumeMotionCancel();
6887
6888 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6889 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6890}
6891
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006892/**
6893 * Two windows, one on the left and another on the right. The left window is slippery. The right
6894 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6895 * touch moves from the left window into the right window, the gesture should continue to go to the
6896 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6897 * reproduces a crash.
6898 */
6899TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6901
6902 sp<FakeWindowHandle> leftSlipperyWindow =
6903 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6904 leftSlipperyWindow->setSlippery(true);
6905 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6906
6907 sp<FakeWindowHandle> rightDropTouchesWindow =
6908 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6909 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6910 rightDropTouchesWindow->setDropInput(true);
6911
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006912 mDispatcher->onWindowInfosChanged(
6913 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006914
6915 // Start touch in the left window
6916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6917 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6918 .build());
6919 leftSlipperyWindow->consumeMotionDown();
6920
6921 // And move it into the right window
6922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6923 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6924 .build());
6925
6926 // Since the right window isn't eligible to receive input, touch does not slip.
6927 // The left window continues to receive the gesture.
6928 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6929 rightDropTouchesWindow->assertNoEvents();
6930}
6931
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006932/**
6933 * A single window is on screen first. Touch is injected into that window. Next, a second window
6934 * appears. Since the first window is slippery, touch will move from the first window to the second.
6935 */
6936TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6938 sp<FakeWindowHandle> originalWindow =
6939 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6940 originalWindow->setFrame(Rect(0, 0, 200, 200));
6941 originalWindow->setSlippery(true);
6942
6943 sp<FakeWindowHandle> appearingWindow =
6944 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6945 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6946
6947 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6948
6949 // Touch down on the original window
6950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6951 injectMotionEvent(*mDispatcher,
6952 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6953 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6954 .build()));
6955 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6956
6957 // Now, a new window appears. This could be, for example, a notification shade that appears
6958 // after user starts to drag down on the launcher window.
6959 mDispatcher->onWindowInfosChanged(
6960 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6962 injectMotionEvent(*mDispatcher,
6963 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6964 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6965 .build()));
6966 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6967 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6969 injectMotionEvent(*mDispatcher,
6970 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6971 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6972 .build()));
6973 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6974
6975 originalWindow->assertNoEvents();
6976 appearingWindow->assertNoEvents();
6977}
6978
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006979TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006980 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006981 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6982
6983 sp<FakeWindowHandle> leftWindow =
6984 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6985 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006986 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006987
6988 sp<FakeWindowHandle> rightSpy =
6989 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6990 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006991 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006992 rightSpy->setSpy(true);
6993 rightSpy->setTrustedOverlay(true);
6994
6995 sp<FakeWindowHandle> rightWindow =
6996 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6997 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006998 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006999
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007000 mDispatcher->onWindowInfosChanged(
7001 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007002
7003 // Touch in the left window
7004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7005 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7006 .build());
7007 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7008 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007009 ASSERT_NO_FATAL_FAILURE(
7010 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007011
7012 // Touch another finger over the right windows
7013 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7014 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7015 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7016 .build());
7017 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7018 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7019 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7020 mDispatcher->waitForIdle();
7021 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007022 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7023 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007024
7025 // Release finger over left window. The UP actions are not treated as device interaction.
7026 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7027 // is part of the UP action, we do not treat this as device interaction.
7028 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7029 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7030 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7031 .build());
7032 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7033 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7034 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7035 mDispatcher->waitForIdle();
7036 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7037
7038 // Move remaining finger
7039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7040 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7041 .build());
7042 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7043 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7044 mDispatcher->waitForIdle();
7045 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007046 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007047
7048 // Release all fingers
7049 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7050 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7051 .build());
7052 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7053 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7054 mDispatcher->waitForIdle();
7055 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7056}
7057
7058TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7059 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7060
7061 sp<FakeWindowHandle> window =
7062 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7063 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007064 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007065
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007067 setFocusedWindow(window);
7068 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7069
7070 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7071 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7072 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007073 ASSERT_NO_FATAL_FAILURE(
7074 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007075
7076 // The UP actions are not treated as device interaction.
7077 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7078 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7079 mDispatcher->waitForIdle();
7080 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7081}
7082
Prabir Pradhan5893d362023-11-17 04:30:40 +00007083TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7084 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7085
7086 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7087 ADISPLAY_ID_DEFAULT);
7088 left->setFrame(Rect(0, 0, 100, 100));
7089 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7090 "Right Window", ADISPLAY_ID_DEFAULT);
7091 right->setFrame(Rect(100, 0, 200, 100));
7092 sp<FakeWindowHandle> spy =
7093 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7094 spy->setFrame(Rect(0, 0, 200, 100));
7095 spy->setTrustedOverlay(true);
7096 spy->setSpy(true);
7097
7098 mDispatcher->onWindowInfosChanged(
7099 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7100
7101 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7102 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7103 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7104 mDispatcher->notifyMotion(notifyArgs);
7105
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007106 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007107 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7108 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007109 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007110 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7111 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007112 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007113 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7114
7115 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7116 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7117 {PointF{150, 50}});
7118 mDispatcher->notifyMotion(notifyArgs);
7119
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007120 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007121 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7122 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007123 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007124 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7125 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007126 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007127 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7128
7129 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7130}
7131
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007132class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7133protected:
7134 std::shared_ptr<FakeApplicationHandle> mApp;
7135 sp<FakeWindowHandle> mWindow;
7136
7137 virtual void SetUp() override {
7138 InputDispatcherTest::SetUp();
7139
7140 mApp = std::make_shared<FakeApplicationHandle>();
7141
7142 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7143 mWindow->setFrame(Rect(0, 0, 100, 100));
7144
7145 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7146 setFocusedWindow(mWindow);
7147 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7148 }
7149
7150 void setFallback(int32_t keycode) {
7151 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7152 return KeyEventBuilder(event).keyCode(keycode).build();
7153 });
7154 }
7155
7156 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007157 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7158 ASSERT_NE(nullptr, event);
7159 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007160 }
7161};
7162
7163TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7164 mDispatcher->notifyKey(
7165 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7166 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7167 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7168}
7169
7170TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7171 mDispatcher->notifyKey(
7172 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7173 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7174 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7175}
7176
7177TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7178 mDispatcher->notifyKey(
7179 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7180
7181 // Do not handle this key event.
7182 consumeKey(/*handled=*/false,
7183 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7184 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7185
7186 // Since the policy did not request any fallback to be generated, ensure there are no events.
7187 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7188}
7189
7190TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7191 setFallback(AKEYCODE_B);
7192 mDispatcher->notifyKey(
7193 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7194
7195 // Do not handle this key event.
7196 consumeKey(/*handled=*/false,
7197 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7198
7199 // Since the key was not handled, ensure the fallback event was dispatched instead.
7200 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7201 consumeKey(/*handled=*/true,
7202 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7203 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7204
7205 // Release the original key, and ensure the fallback key is also released.
7206 mDispatcher->notifyKey(
7207 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7208 consumeKey(/*handled=*/false,
7209 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7210 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7211 consumeKey(/*handled=*/true,
7212 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7213 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7214
7215 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7216 mWindow->assertNoEvents();
7217}
7218
7219TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7220 setFallback(AKEYCODE_B);
7221 mDispatcher->notifyKey(
7222 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7223
7224 // Do not handle this key event, but handle the fallback.
7225 consumeKey(/*handled=*/false,
7226 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7227 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7228 consumeKey(/*handled=*/true,
7229 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7230 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7231
7232 // Release the original key, and ensure the fallback key is also released.
7233 mDispatcher->notifyKey(
7234 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7235 // But this time, the app handles the original key.
7236 consumeKey(/*handled=*/true,
7237 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7238 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7239 // Ensure the fallback key is canceled.
7240 consumeKey(/*handled=*/true,
7241 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7242 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7243
7244 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7245 mWindow->assertNoEvents();
7246}
7247
7248TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7249 setFallback(AKEYCODE_B);
7250 mDispatcher->notifyKey(
7251 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7252
7253 // Do not handle this key event.
7254 consumeKey(/*handled=*/false,
7255 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7256 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7257 // App does not handle the fallback either, so ensure another fallback is not generated.
7258 setFallback(AKEYCODE_C);
7259 consumeKey(/*handled=*/false,
7260 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7261 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7262
7263 // Release the original key, and ensure the fallback key is also released.
7264 setFallback(AKEYCODE_B);
7265 mDispatcher->notifyKey(
7266 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7267 consumeKey(/*handled=*/false,
7268 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7269 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7270 consumeKey(/*handled=*/false,
7271 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7272 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7273
7274 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7275 mWindow->assertNoEvents();
7276}
7277
7278TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7279 setFallback(AKEYCODE_B);
7280 mDispatcher->notifyKey(
7281 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7282
7283 // Do not handle this key event, so fallback is generated.
7284 consumeKey(/*handled=*/false,
7285 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7286 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7287 consumeKey(/*handled=*/true,
7288 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7289 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7290
7291 // Release the original key, but assume the policy is misbehaving and it
7292 // generates an inconsistent fallback to the one from the DOWN event.
7293 setFallback(AKEYCODE_C);
7294 mDispatcher->notifyKey(
7295 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7296 consumeKey(/*handled=*/false,
7297 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7298 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7299 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7300 consumeKey(/*handled=*/true,
7301 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7302 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7303
7304 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7305 mWindow->assertNoEvents();
7306}
7307
7308TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7309 setFallback(AKEYCODE_B);
7310 mDispatcher->notifyKey(
7311 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7312
7313 // Do not handle this key event, so fallback is generated.
7314 consumeKey(/*handled=*/false,
7315 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7316 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7317 consumeKey(/*handled=*/true,
7318 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7319 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7320
7321 // The original key is canceled.
7322 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7323 .keyCode(AKEYCODE_A)
7324 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7325 .build());
7326 consumeKey(/*handled=*/false,
7327 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7328 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7329 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7330 // Ensure the fallback key is also canceled due to the original key being canceled.
7331 consumeKey(/*handled=*/true,
7332 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7333 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7334
7335 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7336 mWindow->assertNoEvents();
7337}
7338
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007339TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007340 setFallback(AKEYCODE_B);
7341 mDispatcher->notifyKey(
7342 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7343
7344 // Do not handle this key event.
7345 consumeKey(/*handled=*/false,
7346 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7347 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7348 consumeKey(/*handled=*/true,
7349 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7350 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7351
7352 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7353 // When the unhandled key is reported to the policy next, remove the input channel.
7354 mDispatcher->removeInputChannel(mWindow->getToken());
7355 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7356 });
7357 // Release the original key, and let the app now handle the previously unhandled key.
7358 // This should result in the previously generated fallback key to be cancelled.
7359 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7360 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7361 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7362 // the policy call, we will now remove the input channel. Once the policy call returns, the
7363 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7364 // not cause any crashes.
7365 mDispatcher->notifyKey(
7366 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7367 consumeKey(/*handled=*/true,
7368 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7369 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7370}
7371
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007372TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7373 setFallback(AKEYCODE_B);
7374 mDispatcher->notifyKey(
7375 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7376
7377 // Do not handle this key event.
7378 consumeKey(/*handled=*/false,
7379 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7380 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7381 consumeKey(/*handled=*/true,
7382 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7383 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7384
7385 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7386 // When the unhandled key is reported to the policy next, remove the window.
7387 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7388 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7389 });
7390 // Release the original key, which the app will not handle. When this unhandled key is reported
7391 // to the policy, the window will be removed.
7392 mDispatcher->notifyKey(
7393 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7394 consumeKey(/*handled=*/false,
7395 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7396 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7397
7398 // Since the window was removed, it loses focus, and the channel state will be reset.
7399 consumeKey(/*handled=*/true,
7400 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7401 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7402 mWindow->consumeFocusEvent(false);
7403 mWindow->assertNoEvents();
7404}
7405
7406TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7407 setFallback(AKEYCODE_B);
7408 mDispatcher->notifyKey(
7409 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7410
7411 // Do not handle this key event.
7412 consumeKey(/*handled=*/false,
7413 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7414 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7415 const auto [seq, event] = mWindow->receiveEvent();
7416 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7417 ASSERT_EQ(event->getType(), InputEventType::KEY);
7418 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7419 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7420 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7421
7422 // Remove the window now, which should generate a cancellations and make the window lose focus.
7423 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7424 consumeKey(/*handled=*/true,
7425 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7426 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7427 consumeKey(/*handled=*/true,
7428 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7429 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7430 mWindow->consumeFocusEvent(false);
7431
7432 // Finish the event by reporting it as handled.
7433 mWindow->finishEvent(*seq);
7434 mWindow->assertNoEvents();
7435}
7436
Garfield Tan1c7bc862020-01-28 13:24:04 -08007437class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7438protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007439 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7440 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007441
Chris Yea209fde2020-07-22 13:54:51 -07007442 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007443 sp<FakeWindowHandle> mWindow;
7444
7445 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007446 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007447
Prabir Pradhandae52792023-12-15 07:36:40 +00007448 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007449 setUpWindow();
7450 }
7451
7452 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007453 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007454 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007455
Vishnu Nair47074b82020-08-14 11:54:47 -07007456 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007457 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007458 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007459 mWindow->consumeFocusEvent(true);
7460 }
7461
Chris Ye2ad95392020-09-01 13:44:44 -07007462 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007463 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007464 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007465 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007466 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007467
7468 // Window should receive key down event.
7469 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7470 }
7471
7472 void expectKeyRepeatOnce(int32_t repeatCount) {
7473 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007474 mWindow->consumeKeyEvent(
7475 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007476 }
7477
Chris Ye2ad95392020-09-01 13:44:44 -07007478 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007479 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007480 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007481 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007482 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007483
7484 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007485 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007486 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007487 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007488
7489 void injectKeyRepeat(int32_t repeatCount) {
7490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7491 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7492 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7493 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007494};
7495
7496TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007497 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007498 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7499 expectKeyRepeatOnce(repeatCount);
7500 }
7501}
7502
7503TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007504 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007505 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7506 expectKeyRepeatOnce(repeatCount);
7507 }
Harry Cutts33476232023-01-30 19:57:29 +00007508 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007509 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007510 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7511 expectKeyRepeatOnce(repeatCount);
7512 }
7513}
7514
7515TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007516 sendAndConsumeKeyDown(/*deviceId=*/1);
7517 expectKeyRepeatOnce(/*repeatCount=*/1);
7518 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007519 mWindow->assertNoEvents();
7520}
7521
7522TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007523 sendAndConsumeKeyDown(/*deviceId=*/1);
7524 expectKeyRepeatOnce(/*repeatCount=*/1);
7525 sendAndConsumeKeyDown(/*deviceId=*/2);
7526 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007527 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007528 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007529 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007530 expectKeyRepeatOnce(/*repeatCount=*/2);
7531 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007532 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007533 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007534 mWindow->assertNoEvents();
7535}
7536
7537TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007538 sendAndConsumeKeyDown(/*deviceId=*/1);
7539 expectKeyRepeatOnce(/*repeatCount=*/1);
7540 sendAndConsumeKeyDown(/*deviceId=*/2);
7541 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007542 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007543 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007544 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007545 mWindow->assertNoEvents();
7546}
7547
liushenxiang42232912021-05-21 20:24:09 +08007548TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7549 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007550 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007551 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007552 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7553 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7554 mWindow->assertNoEvents();
7555}
7556
Garfield Tan1c7bc862020-01-28 13:24:04 -08007557TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007558 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007559 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007560 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007561 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7562 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007563 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007564 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007565 }
7566}
7567
7568TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007569 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007570 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007571
7572 std::unordered_set<int32_t> idSet;
7573 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007574 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7575 ASSERT_NE(nullptr, repeatEvent);
7576 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007577 EXPECT_EQ(idSet.end(), idSet.find(id));
7578 idSet.insert(id);
7579 }
7580}
7581
Hu Guofe3c8f12023-09-22 17:20:15 +08007582TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7583 injectKeyRepeat(0);
7584 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7585 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7586 expectKeyRepeatOnce(repeatCount);
7587 }
7588 injectKeyRepeat(1);
7589 // Expect repeatCount to be 3 instead of 1
7590 expectKeyRepeatOnce(3);
7591}
7592
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007593/* Test InputDispatcher for MultiDisplay */
7594class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7595public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007596 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007597 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007598
Chris Yea209fde2020-07-22 13:54:51 -07007599 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007600 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007601 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007602
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007603 // Set focus window for primary display, but focused display would be second one.
7604 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007605 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007606 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7607
Vishnu Nair958da932020-08-21 17:12:37 -07007608 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007609 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007610
Chris Yea209fde2020-07-22 13:54:51 -07007611 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007612 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007613 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007614 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007615 // Set focus display to second one.
7616 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7617 // Set focus window for second display.
7618 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007619 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007620 mDispatcher->onWindowInfosChanged(
7621 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007622 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007623 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007624 }
7625
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007626 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007627 InputDispatcherTest::TearDown();
7628
Chris Yea209fde2020-07-22 13:54:51 -07007629 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007630 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007631 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007632 windowInSecondary.clear();
7633 }
7634
7635protected:
Chris Yea209fde2020-07-22 13:54:51 -07007636 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007637 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007638 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007639 sp<FakeWindowHandle> windowInSecondary;
7640};
7641
7642TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7643 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007645 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007647 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007648 windowInSecondary->assertNoEvents();
7649
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007650 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007652 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007653 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007654 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007655 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007656}
7657
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007658TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007659 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007661 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007662 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007663 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007664 windowInSecondary->assertNoEvents();
7665
7666 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007668 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007669 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007670 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007671
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007672 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007673 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007674
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007675 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007676 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007677
7678 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007679 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007680 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007681 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007682 windowInSecondary->assertNoEvents();
7683}
7684
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007685// Test per-display input monitors for motion event.
7686TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007687 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007688 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007689 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007690 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007691
7692 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007694 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007696 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007697 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007698 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007699 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007700
7701 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007703 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007705 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007706 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007707 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007708 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007709
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007710 // Lift up the touch from the second display
7711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007712 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7714 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7715 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7716
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007717 // Test inject a non-pointer motion event.
7718 // If specific a display, it will dispatch to the focused window of particular display,
7719 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007721 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007723 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007724 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007725 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007726 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007727}
7728
7729// Test per-display input monitors for key event.
7730TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007731 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007732 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007733 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007734 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007735 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007736
7737 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007739 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007740 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007741 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007742 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007743 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007744}
7745
Vishnu Nair958da932020-08-21 17:12:37 -07007746TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7747 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007748 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007749 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007750 mDispatcher->onWindowInfosChanged(
7751 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7752 *windowInSecondary->getInfo()},
7753 {},
7754 0,
7755 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007756 setFocusedWindow(secondWindowInPrimary);
7757 windowInPrimary->consumeFocusEvent(false);
7758 secondWindowInPrimary->consumeFocusEvent(true);
7759
7760 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007761 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7762 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007764 windowInPrimary->assertNoEvents();
7765 windowInSecondary->assertNoEvents();
7766 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7767}
7768
Arthur Hungdfd528e2021-12-08 13:23:04 +00007769TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7770 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007771 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007772 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007773 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007774
7775 // Test touch down on primary display.
7776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7779 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7780 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7781
7782 // Test touch down on second display.
7783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007784 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007785 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7786 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7787 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7788
7789 // Trigger cancel touch.
7790 mDispatcher->cancelCurrentTouch();
7791 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7792 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7793 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7794 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7795
7796 // Test inject a move motion event, no window/monitor should receive the event.
7797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007798 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007799 ADISPLAY_ID_DEFAULT, {110, 200}))
7800 << "Inject motion event should return InputEventInjectionResult::FAILED";
7801 windowInPrimary->assertNoEvents();
7802 monitorInPrimary.assertNoEvents();
7803
7804 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007805 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007806 SECOND_DISPLAY_ID, {110, 200}))
7807 << "Inject motion event should return InputEventInjectionResult::FAILED";
7808 windowInSecondary->assertNoEvents();
7809 monitorInSecondary.assertNoEvents();
7810}
7811
Hu Guocb134f12023-12-23 13:42:44 +00007812/**
7813 * Send a key to the primary display and to the secondary display.
7814 * Then cause the key on the primary display to be canceled by sending in a stale key.
7815 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7816 * does not get canceled.
7817 */
7818TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7819 // Send a key down on primary display
7820 mDispatcher->notifyKey(
7821 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7822 .displayId(ADISPLAY_ID_DEFAULT)
7823 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7824 .build());
7825 windowInPrimary->consumeKeyEvent(
7826 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7827 windowInSecondary->assertNoEvents();
7828
7829 // Send a key down on second display
7830 mDispatcher->notifyKey(
7831 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7832 .displayId(SECOND_DISPLAY_ID)
7833 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7834 .build());
7835 windowInSecondary->consumeKeyEvent(
7836 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7837 windowInPrimary->assertNoEvents();
7838
7839 // Send a valid key up event on primary display that will be dropped because it is stale
7840 NotifyKeyArgs staleKeyUp =
7841 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7842 .displayId(ADISPLAY_ID_DEFAULT)
7843 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7844 .build();
7845 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7846 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7847 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7848 mDispatcher->notifyKey(staleKeyUp);
7849
7850 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7851 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7852 // receive any events.
7853 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7854 WithDisplayId(ADISPLAY_ID_DEFAULT),
7855 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7856 windowInSecondary->assertNoEvents();
7857}
7858
7859/**
7860 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7861 */
7862TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7863 // Send touch down on primary display.
7864 mDispatcher->notifyMotion(
7865 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7866 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7867 .displayId(ADISPLAY_ID_DEFAULT)
7868 .build());
7869 windowInPrimary->consumeMotionEvent(
7870 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7871 windowInSecondary->assertNoEvents();
7872
7873 // Send touch down on second display.
7874 mDispatcher->notifyMotion(
7875 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7876 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7877 .displayId(SECOND_DISPLAY_ID)
7878 .build());
7879 windowInPrimary->assertNoEvents();
7880 windowInSecondary->consumeMotionEvent(
7881 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7882
7883 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7884 NotifyMotionArgs staleMotionUp =
7885 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7886 .displayId(ADISPLAY_ID_DEFAULT)
7887 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7888 .build();
7889 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7890 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7891 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7892 mDispatcher->notifyMotion(staleMotionUp);
7893
7894 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7895 // events, where we would cancel the current keys instead.
7896 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7897 windowInSecondary->assertNoEvents();
7898}
7899
Jackal Guof9696682018-10-05 12:23:23 +08007900class InputFilterTest : public InputDispatcherTest {
7901protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007902 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7903 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007904 NotifyMotionArgs motionArgs;
7905
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007906 motionArgs =
7907 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007908 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007909 motionArgs =
7910 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007911 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007912 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007913 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007914 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007915 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007916 } else {
7917 mFakePolicy->assertFilterInputEventWasNotCalled();
7918 }
7919 }
7920
7921 void testNotifyKey(bool expectToBeFiltered) {
7922 NotifyKeyArgs keyArgs;
7923
7924 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007925 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007926 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007927 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007928 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007929
7930 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007931 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007932 } else {
7933 mFakePolicy->assertFilterInputEventWasNotCalled();
7934 }
7935 }
7936};
7937
7938// Test InputFilter for MotionEvent
7939TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7940 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007941 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7942 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007943
7944 // Enable InputFilter
7945 mDispatcher->setInputFilterEnabled(true);
7946 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007947 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7948 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007949
7950 // Disable InputFilter
7951 mDispatcher->setInputFilterEnabled(false);
7952 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007953 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7954 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007955}
7956
7957// Test InputFilter for KeyEvent
7958TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7959 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007960 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007961
7962 // Enable InputFilter
7963 mDispatcher->setInputFilterEnabled(true);
7964 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007965 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007966
7967 // Disable InputFilter
7968 mDispatcher->setInputFilterEnabled(false);
7969 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007970 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007971}
7972
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007973// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7974// logical display coordinate space.
7975TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7976 ui::Transform firstDisplayTransform;
7977 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7978 ui::Transform secondDisplayTransform;
7979 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7980
7981 std::vector<gui::DisplayInfo> displayInfos(2);
7982 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7983 displayInfos[0].transform = firstDisplayTransform;
7984 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7985 displayInfos[1].transform = secondDisplayTransform;
7986
Patrick Williamsd828f302023-04-28 17:52:08 -05007987 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007988
7989 // Enable InputFilter
7990 mDispatcher->setInputFilterEnabled(true);
7991
7992 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007993 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7994 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007995}
7996
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007997class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7998protected:
7999 virtual void SetUp() override {
8000 InputDispatcherTest::SetUp();
8001
8002 /**
8003 * We don't need to enable input filter to test the injected event policy, but we enabled it
8004 * here to make the tests more realistic, since this policy only matters when inputfilter is
8005 * on.
8006 */
8007 mDispatcher->setInputFilterEnabled(true);
8008
8009 std::shared_ptr<InputApplicationHandle> application =
8010 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008011 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8012 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008013
8014 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8015 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008016 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008017 setFocusedWindow(mWindow);
8018 mWindow->consumeFocusEvent(true);
8019 }
8020
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008021 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8022 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008023 KeyEvent event;
8024
8025 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8026 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8027 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008028 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008029 const int32_t additionalPolicyFlags =
8030 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008032 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008033 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008034 policyFlags | additionalPolicyFlags));
8035
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008036 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008037 }
8038
8039 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8040 int32_t flags) {
8041 MotionEvent event;
8042 PointerProperties pointerProperties[1];
8043 PointerCoords pointerCoords[1];
8044 pointerProperties[0].clear();
8045 pointerProperties[0].id = 0;
8046 pointerCoords[0].clear();
8047 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8048 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8049
8050 ui::Transform identityTransform;
8051 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8052 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8053 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8054 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8055 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008056 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008057 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008058 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008059
8060 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008062 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008063 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008064 policyFlags | additionalPolicyFlags));
8065
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008066 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008067 }
8068
8069private:
8070 sp<FakeWindowHandle> mWindow;
8071};
8072
8073TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008074 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8075 // filter. Without it, the event will no different from a regularly injected event, and the
8076 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008077 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8078 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008079}
8080
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008081TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008082 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008083 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008084 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8085}
8086
8087TEST_F(InputFilterInjectionPolicyTest,
8088 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8089 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008090 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008091 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008092}
8093
8094TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008095 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8096 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008097}
8098
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008099class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8100protected:
8101 virtual void SetUp() override {
8102 InputDispatcherTest::SetUp();
8103
8104 std::shared_ptr<FakeApplicationHandle> application =
8105 std::make_shared<FakeApplicationHandle>();
8106 application->setDispatchingTimeout(100ms);
8107 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8108 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008109 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008110 mWindow->setDispatchingTimeout(100ms);
8111 mWindow->setFocusable(true);
8112
8113 // Set focused application.
8114 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8115
8116 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8117 setFocusedWindow(mWindow);
8118 mWindow->consumeFocusEvent(true);
8119 }
8120
8121 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8122 nsecs_t eventTime) {
8123 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8124 .displayId(displayId)
8125 .eventTime(eventTime)
8126 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8127 .build());
8128 mWindow->consumeMotionEvent(WithMotionAction(action));
8129 }
8130
8131private:
8132 sp<FakeWindowHandle> mWindow;
8133};
8134
8135TEST_F_WITH_FLAGS(
8136 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8137 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8138 rate_limit_user_activity_poke_in_dispatcher))) {
8139 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8140
8141 // First event of type TOUCH. Should poke.
8142 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8143 milliseconds_to_nanoseconds(50));
8144 mFakePolicy->assertUserActivityPoked(
8145 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8146
8147 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8148 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8149 milliseconds_to_nanoseconds(130));
8150 mFakePolicy->assertUserActivityPoked(
8151 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8152
8153 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8154 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8155 milliseconds_to_nanoseconds(135));
8156 mFakePolicy->assertUserActivityPoked(
8157 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8158
8159 // Within 50ns of previous TOUCH event. Should NOT poke.
8160 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8161 milliseconds_to_nanoseconds(140));
8162 mFakePolicy->assertUserActivityNotPoked();
8163
8164 // Within 50ns of previous OTHER event. Should NOT poke.
8165 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8166 milliseconds_to_nanoseconds(150));
8167 mFakePolicy->assertUserActivityNotPoked();
8168
8169 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8170 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8171 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8172 milliseconds_to_nanoseconds(160));
8173 mFakePolicy->assertUserActivityNotPoked();
8174
8175 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8176 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8177 milliseconds_to_nanoseconds(200));
8178 mFakePolicy->assertUserActivityPoked(
8179 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8180
8181 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8182 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8183 milliseconds_to_nanoseconds(300));
8184 mFakePolicy->assertUserActivityPoked(
8185 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8186
8187 // Assert that there's no more user activity poke event.
8188 mFakePolicy->assertUserActivityNotPoked();
8189}
8190
8191TEST_F_WITH_FLAGS(
8192 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8193 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8194 rate_limit_user_activity_poke_in_dispatcher))) {
8195 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8196 milliseconds_to_nanoseconds(200));
8197 mFakePolicy->assertUserActivityPoked(
8198 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8199
8200 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8201 milliseconds_to_nanoseconds(280));
8202 mFakePolicy->assertUserActivityNotPoked();
8203
8204 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8205 milliseconds_to_nanoseconds(340));
8206 mFakePolicy->assertUserActivityPoked(
8207 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8208}
8209
8210TEST_F_WITH_FLAGS(
8211 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8212 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8213 rate_limit_user_activity_poke_in_dispatcher))) {
8214 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8215
8216 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8217 mFakePolicy->assertUserActivityPoked();
8218
8219 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8220 mFakePolicy->assertUserActivityPoked();
8221}
8222
chaviwfd6d3512019-03-25 13:23:49 -07008223class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008224 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008225 InputDispatcherTest::SetUp();
8226
Chris Yea209fde2020-07-22 13:54:51 -07008227 std::shared_ptr<FakeApplicationHandle> application =
8228 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008229 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008230 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008231 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008232
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008233 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008234 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008235 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008236
8237 // Set focused application.
8238 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008239 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008240
8241 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008242 mDispatcher->onWindowInfosChanged(
8243 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008244 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008245 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008246 }
8247
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008248 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008249 InputDispatcherTest::TearDown();
8250
8251 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008252 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008253 }
8254
8255protected:
8256 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008257 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008258 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008259};
8260
8261// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8262// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8263// the onPointerDownOutsideFocus callback.
8264TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008266 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008267 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008268 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008269 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008270
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008271 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008272 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8273}
8274
8275// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8276// DOWN on the window that doesn't have focus. Ensure no window received the
8277// onPointerDownOutsideFocus callback.
8278TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008280 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8281 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008282 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008283 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008284
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008285 ASSERT_TRUE(mDispatcher->waitForIdle());
8286 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008287}
8288
8289// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8290// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8291TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008293 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008294 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008295 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008296
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008297 ASSERT_TRUE(mDispatcher->waitForIdle());
8298 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008299}
8300
8301// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8302// DOWN on the window that already has focus. Ensure no window received the
8303// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008304TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008305 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008306 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008307 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008308 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008309 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008310
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008311 ASSERT_TRUE(mDispatcher->waitForIdle());
8312 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008313}
8314
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008315// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8316// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8317TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8318 const MotionEvent event =
8319 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8320 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008321 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008322 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8323 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8326 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8327
8328 ASSERT_TRUE(mDispatcher->waitForIdle());
8329 mFakePolicy->assertOnPointerDownWasNotCalled();
8330 // Ensure that the unfocused window did not receive any FOCUS events.
8331 mUnfocusedWindow->assertNoEvents();
8332}
8333
chaviwaf87b3e2019-10-01 16:59:28 -07008334// These tests ensures we can send touch events to a single client when there are multiple input
8335// windows that point to the same client token.
8336class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8337 virtual void SetUp() override {
8338 InputDispatcherTest::SetUp();
8339
Chris Yea209fde2020-07-22 13:54:51 -07008340 std::shared_ptr<FakeApplicationHandle> application =
8341 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008342 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8343 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008344 mWindow1->setFrame(Rect(0, 0, 100, 100));
8345
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008346 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008347 mWindow2->setFrame(Rect(100, 100, 200, 200));
8348
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008349 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008350 }
8351
8352protected:
8353 sp<FakeWindowHandle> mWindow1;
8354 sp<FakeWindowHandle> mWindow2;
8355
8356 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008357 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008358 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8359 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008360 }
8361
8362 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8363 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008364 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008365 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008366 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008367 ASSERT_NE(nullptr, motionEvent);
8368 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008369
8370 for (size_t i = 0; i < points.size(); i++) {
8371 float expectedX = points[i].x;
8372 float expectedY = points[i].y;
8373
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008374 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008375 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008376 << ", got " << motionEvent->getX(i);
8377 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008378 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008379 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008380 }
8381 }
chaviw9eaa22c2020-07-01 16:21:27 -07008382
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008383 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8384 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008385 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008386 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8387 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008388
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008389 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008390 }
chaviwaf87b3e2019-10-01 16:59:28 -07008391};
8392
8393TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8394 // Touch Window 1
8395 PointF touchedPoint = {10, 10};
8396 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008397 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008398
8399 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008400 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008401
8402 // Touch Window 2
8403 touchedPoint = {150, 150};
8404 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008405 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008406}
8407
chaviw9eaa22c2020-07-01 16:21:27 -07008408TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8409 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008410 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008411 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008412
8413 // Touch Window 1
8414 PointF touchedPoint = {10, 10};
8415 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008416 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008417 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008418 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008419
8420 // Touch Window 2
8421 touchedPoint = {150, 150};
8422 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008423 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8424 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008425
chaviw9eaa22c2020-07-01 16:21:27 -07008426 // Update the transform so rotation is set
8427 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008428 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008429 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008430 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008431}
8432
chaviw9eaa22c2020-07-01 16:21:27 -07008433TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008434 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008435 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008436
8437 // Touch Window 1
8438 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8439 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008440 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008441
8442 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008443 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8444 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8445 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008446 touchedPoints.push_back(PointF{150, 150});
8447 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008448 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008449
chaviw9eaa22c2020-07-01 16:21:27 -07008450 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008451 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008452 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008453
chaviw9eaa22c2020-07-01 16:21:27 -07008454 // Update the transform so rotation is set for Window 2
8455 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008456 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008457 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008458 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008459}
8460
chaviw9eaa22c2020-07-01 16:21:27 -07008461TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008462 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008463 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008464
8465 // Touch Window 1
8466 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8467 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008468 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008469
8470 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008471 touchedPoints.push_back(PointF{150, 150});
8472 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008473
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008474 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008475
8476 // Move both windows
8477 touchedPoints = {{20, 20}, {175, 175}};
8478 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8479 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8480
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008481 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008482
chaviw9eaa22c2020-07-01 16:21:27 -07008483 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008484 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008485 expectedPoints.pop_back();
8486
8487 // Touch Window 2
8488 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008489 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008490 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008491 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008492
8493 // Move both windows
8494 touchedPoints = {{20, 20}, {175, 175}};
8495 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8496 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8497
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008498 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008499}
8500
8501TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8502 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008503 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008504
8505 // Touch Window 1
8506 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8507 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008508 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008509
8510 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008511 touchedPoints.push_back(PointF{150, 150});
8512 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008513
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008514 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008515
8516 // Move both windows
8517 touchedPoints = {{20, 20}, {175, 175}};
8518 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8519 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8520
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008521 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008522}
8523
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008524/**
8525 * When one of the windows is slippery, the touch should not slip into the other window with the
8526 * same input channel.
8527 */
8528TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8529 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008530 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008531
8532 // Touch down in window 1
8533 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8534 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8535 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8536
8537 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8538 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8539 // getting generated.
8540 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8541 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8542
8543 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8544}
8545
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008546/**
8547 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8548 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8549 * that the pointer is hovering over may have a different transform.
8550 */
8551TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008552 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008553
8554 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8556 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8557 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008558 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8559 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008560 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8562 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8563 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008564 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008565 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008566 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8567}
8568
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008569class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8570 virtual void SetUp() override {
8571 InputDispatcherTest::SetUp();
8572
Chris Yea209fde2020-07-22 13:54:51 -07008573 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008574 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008575 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8576 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008577 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008578 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008579 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008580
8581 // Set focused application.
8582 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8583
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008584 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008585 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008586 mWindow->consumeFocusEvent(true);
8587 }
8588
8589 virtual void TearDown() override {
8590 InputDispatcherTest::TearDown();
8591 mWindow.clear();
8592 }
8593
8594protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008595 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008596 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008597 sp<FakeWindowHandle> mWindow;
8598 static constexpr PointF WINDOW_LOCATION = {20, 20};
8599
8600 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008601 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8602 .x(WINDOW_LOCATION.x)
8603 .y(WINDOW_LOCATION.y);
8604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8605 .pointer(touchingPointer)
8606 .build());
8607 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8608 .pointer(touchingPointer)
8609 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008610 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008611
8612 sp<FakeWindowHandle> addSpyWindow() {
8613 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008614 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008615 spy->setTrustedOverlay(true);
8616 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008617 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008618 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008619 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008620 return spy;
8621 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008622};
8623
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008624// Send a tap and respond, which should not cause an ANR.
8625TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8626 tapOnWindow();
8627 mWindow->consumeMotionDown();
8628 mWindow->consumeMotionUp();
8629 ASSERT_TRUE(mDispatcher->waitForIdle());
8630 mFakePolicy->assertNotifyAnrWasNotCalled();
8631}
8632
8633// Send a regular key and respond, which should not cause an ANR.
8634TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008636 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8637 ASSERT_TRUE(mDispatcher->waitForIdle());
8638 mFakePolicy->assertNotifyAnrWasNotCalled();
8639}
8640
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008641TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8642 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008643 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008644 mWindow->consumeFocusEvent(false);
8645
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008646 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008647 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8648 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008649 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008651 // Key will not go to window because we have no focused window.
8652 // The 'no focused window' ANR timer should start instead.
8653
8654 // Now, the focused application goes away.
8655 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8656 // The key should get dropped and there should be no ANR.
8657
8658 ASSERT_TRUE(mDispatcher->waitForIdle());
8659 mFakePolicy->assertNotifyAnrWasNotCalled();
8660}
8661
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008662// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8664// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008665TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008667 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008668 WINDOW_LOCATION));
8669
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008670 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008671 ASSERT_TRUE(sequenceNum);
8672 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008673 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008674
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008675 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008676 mWindow->consumeMotionEvent(
8677 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008678 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008679 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008680}
8681
8682// Send a key to the app and have the app not respond right away.
8683TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8684 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008686 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008687 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008688 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008689 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008690 ASSERT_TRUE(mDispatcher->waitForIdle());
8691}
8692
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008693// We have a focused application, but no focused window
8694TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008695 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008696 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008697 mWindow->consumeFocusEvent(false);
8698
8699 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008701 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008702 WINDOW_LOCATION));
8703 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8704 mDispatcher->waitForIdle();
8705 mFakePolicy->assertNotifyAnrWasNotCalled();
8706
8707 // Once a focused event arrives, we get an ANR for this application
8708 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8709 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008710 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008711 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008712 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008713 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008714 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008715 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008716 ASSERT_TRUE(mDispatcher->waitForIdle());
8717}
8718
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008719/**
8720 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8721 * there will not be an ANR.
8722 */
8723TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8724 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008725 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008726 mWindow->consumeFocusEvent(false);
8727
8728 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008729 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8730 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008731 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8732 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8733
8734 // Define a valid key down event that is stale (too old).
8735 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008736 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008737 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008738
Hu Guofe3c8f12023-09-22 17:20:15 +08008739 const int32_t policyFlags =
8740 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008741
8742 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008743 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008744 InputEventInjectionSync::WAIT_FOR_RESULT,
8745 INJECT_EVENT_TIMEOUT, policyFlags);
8746 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8747 << "Injection should fail because the event is stale";
8748
8749 ASSERT_TRUE(mDispatcher->waitForIdle());
8750 mFakePolicy->assertNotifyAnrWasNotCalled();
8751 mWindow->assertNoEvents();
8752}
8753
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008754// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008755// Make sure that we don't notify policy twice about the same ANR.
8756TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008757 const std::chrono::duration appTimeout = 400ms;
8758 mApplication->setDispatchingTimeout(appTimeout);
8759 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8760
Vishnu Nair47074b82020-08-14 11:54:47 -07008761 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008762 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008763 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008764
8765 // Once a focused event arrives, we get an ANR for this application
8766 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8767 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008768 const std::chrono::duration eventInjectionTimeout = 100ms;
8769 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008770 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008771 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008772 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8773 /*allowKeyRepeat=*/false);
8774 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8775 << "result=" << ftl::enum_string(result);
8776 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8777 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8778 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8779 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008780
Vishnu Naire4df8752022-09-08 09:17:55 -07008781 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008782 // ANR should not be raised again. It is up to policy to do that if it desires.
8783 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008784
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008785 // If we now get a focused window, the ANR should stop, but the policy handles that via
8786 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008787 ASSERT_TRUE(mDispatcher->waitForIdle());
8788}
8789
8790// We have a focused application, but no focused window
8791TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008792 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008794 mWindow->consumeFocusEvent(false);
8795
8796 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008797 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008798
Vishnu Naire4df8752022-09-08 09:17:55 -07008799 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8800 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008801
8802 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008803 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008804 ASSERT_TRUE(mDispatcher->waitForIdle());
8805 mWindow->assertNoEvents();
8806}
8807
8808/**
8809 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8810 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8811 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8812 * the ANR mechanism should still work.
8813 *
8814 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8815 * DOWN event, while not responding on the second one.
8816 */
8817TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8818 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008819 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008820 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8821 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8822 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008823 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008824
8825 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008826 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008827 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8828 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8829 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008830 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008831
8832 // We have now sent down and up. Let's consume first event and then ANR on the second.
8833 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8834 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008835 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008836}
8837
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008838// A spy window can receive an ANR
8839TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8840 sp<FakeWindowHandle> spy = addSpyWindow();
8841
8842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008844 WINDOW_LOCATION));
8845 mWindow->consumeMotionDown();
8846
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008847 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008848 ASSERT_TRUE(sequenceNum);
8849 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008850 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008851
8852 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008853 spy->consumeMotionEvent(
8854 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008855 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008856 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008857}
8858
8859// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008860// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008861TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8862 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008863
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008865 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008866 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008868
8869 // Stuck on the ACTION_UP
8870 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008871 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008872
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008873 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008874 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008875 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8876 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008877
8878 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8879 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008880 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008881 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008882 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008883}
8884
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008885// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008886// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008887TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8888 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008889
8890 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008891 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8892 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008893
8894 mWindow->consumeMotionDown();
8895 // Stuck on the ACTION_UP
8896 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008897 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008898
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008899 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008900 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008901 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8902 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008903
8904 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8905 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008906 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008907 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008908 spy->assertNoEvents();
8909}
8910
8911TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008912 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008913
Prabir Pradhanfb549072023-10-05 19:17:36 +00008914 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008915
8916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008917 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008918 WINDOW_LOCATION));
8919
8920 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8921 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8922 ASSERT_TRUE(consumeSeq);
8923
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008924 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8925 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008926
8927 monitor.finishEvent(*consumeSeq);
8928 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8929
8930 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008931 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008932}
8933
8934// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8935// process events, you don't get an anr. When the window later becomes unresponsive again, you
8936// get an ANR again.
8937// 1. tap -> block on ACTION_UP -> receive ANR
8938// 2. consume all pending events (= queue becomes healthy again)
8939// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8940TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8941 tapOnWindow();
8942
8943 mWindow->consumeMotionDown();
8944 // Block on ACTION_UP
8945 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008946 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8948 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008949 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008950 mWindow->assertNoEvents();
8951
8952 tapOnWindow();
8953 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008954 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008955 mWindow->consumeMotionUp();
8956
8957 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008958 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008959 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008960 mWindow->assertNoEvents();
8961}
8962
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008963// If a connection remains unresponsive for a while, make sure policy is only notified once about
8964// it.
8965TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008967 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008968 WINDOW_LOCATION));
8969
8970 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008971 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008972 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008973 // 'notifyConnectionUnresponsive' should only be called once per connection
8974 mFakePolicy->assertNotifyAnrWasNotCalled();
8975 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008976 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008977 mWindow->consumeMotionEvent(
8978 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008979 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008980 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008981 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008982 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008983}
8984
8985/**
8986 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008987 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008988 */
8989TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008990 // The timeouts in this test are established by relying on the fact that the "key waiting for
8991 // events timeout" is equal to 500ms.
8992 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008993 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008994 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008995
8996 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008997 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008998 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008999 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009000 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009001
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009002 // Don't finish the events yet, and send a key
9003 mDispatcher->notifyKey(
9004 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9005 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9006 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009007 // Key will not be sent to the window, yet, because the window is still processing events
9008 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009009 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009010 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009011
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009012 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009013 // if we wait long enough though, dispatcher will give up, and still send the key
9014 // to the focused window, even though we have not yet finished the motion event
9015 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9016 mWindow->finishEvent(*downSequenceNum);
9017 mWindow->finishEvent(*upSequenceNum);
9018}
9019
9020/**
9021 * If a window is processing a motion event, and then a key event comes in, the key event should
9022 * not go to the focused window until the motion is processed.
9023 * If then a new motion comes in, then the pending key event should be going to the currently
9024 * focused window right away.
9025 */
9026TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009027 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9028 // The timeouts in this test are established by relying on the fact that the "key waiting for
9029 // events timeout" is equal to 500ms.
9030 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009031 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009032 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009033
9034 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009035 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009036 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009037 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009038 ASSERT_TRUE(upSequenceNum);
9039 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009040 mDispatcher->notifyKey(
9041 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9042 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9043 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009044 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009045 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009046
9047 // Now tap down again. It should cause the pending key to go to the focused window right away.
9048 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009049 // Now that we tapped, we should receive the key immediately.
9050 // Since there's still room for slowness, we use 200ms, which is much less than
9051 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9052 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9053 ASSERT_NE(nullptr, keyEvent);
9054 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9055 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9056 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9057 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009058 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9059 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009060 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9061 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009062 mWindow->assertNoEvents();
9063}
9064
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009065/**
9066 * Send an event to the app and have the app not respond right away.
9067 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9068 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9069 * At some point, the window becomes responsive again.
9070 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9071 */
9072TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9073 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9074 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9075 .build());
9076
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009077 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009078 ASSERT_TRUE(sequenceNum);
9079 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9080 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9081
9082 mWindow->finishEvent(*sequenceNum);
9083 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9084 ASSERT_TRUE(mDispatcher->waitForIdle());
9085 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9086
9087 // Now that the window is responsive, let's continue the gesture.
9088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9089 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9090 .build());
9091
9092 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9093 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9094 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9095 .build());
9096
9097 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9098 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9099 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9100 .build());
9101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9102 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9103 .build());
9104 // We already canceled this pointer, so the window shouldn't get any new events.
9105 mWindow->assertNoEvents();
9106
9107 // Start another one.
9108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9109 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9110 .build());
9111 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9112}
9113
Prabir Pradhanfc364722024-02-08 17:51:20 +00009114// Send an event to the app and have the app not respond right away. Then remove the app window.
9115// When the window is removed, the dispatcher will cancel the events for that window.
9116// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9117TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9118 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9119 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9120 {WINDOW_LOCATION}));
9121
9122 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9123 ASSERT_TRUE(sequenceNum);
9124
9125 // Remove the window, but the input channel should remain alive.
9126 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9127
9128 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9129 // Since the window was removed, Dispatcher does not know the PID associated with the window
9130 // anymore, so the policy is notified without the PID.
9131 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9132 /*pid=*/std::nullopt);
9133
9134 mWindow->finishEvent(*sequenceNum);
9135 // The cancellation was generated when the window was removed, along with the focus event.
9136 mWindow->consumeMotionEvent(
9137 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9138 mWindow->consumeFocusEvent(false);
9139 ASSERT_TRUE(mDispatcher->waitForIdle());
9140 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9141}
9142
9143// Send an event to the app and have the app not respond right away. Wait for the policy to be
9144// notified of the unresponsive window, then remove the app window.
9145TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9146 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9147 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9148 {WINDOW_LOCATION}));
9149
9150 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9151 ASSERT_TRUE(sequenceNum);
9152 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9153 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9154
9155 // Remove the window, but the input channel should remain alive.
9156 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9157
9158 mWindow->finishEvent(*sequenceNum);
9159 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9160 mWindow->consumeMotionEvent(
9161 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9162 mWindow->consumeFocusEvent(false);
9163 ASSERT_TRUE(mDispatcher->waitForIdle());
9164 // Since the window was removed, Dispatcher does not know the PID associated with the window
9165 // becoming responsive, so the policy is notified without the PID.
9166 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9167}
9168
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009169class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9170 virtual void SetUp() override {
9171 InputDispatcherTest::SetUp();
9172
Chris Yea209fde2020-07-22 13:54:51 -07009173 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009174 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009175 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9176 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009177 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009178 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009179 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009180
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009181 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9182 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009183 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009184 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009185
9186 // Set focused application.
9187 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009188 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009189
9190 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009191 mDispatcher->onWindowInfosChanged(
9192 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009193 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009194 mFocusedWindow->consumeFocusEvent(true);
9195 }
9196
9197 virtual void TearDown() override {
9198 InputDispatcherTest::TearDown();
9199
9200 mUnfocusedWindow.clear();
9201 mFocusedWindow.clear();
9202 }
9203
9204protected:
Chris Yea209fde2020-07-22 13:54:51 -07009205 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009206 sp<FakeWindowHandle> mUnfocusedWindow;
9207 sp<FakeWindowHandle> mFocusedWindow;
9208 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9209 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9210 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9211
9212 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9213
9214 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9215
9216private:
9217 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009219 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009220 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009222 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009223 location));
9224 }
9225};
9226
9227// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9228// should be ANR'd first.
9229TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009231 injectMotionEvent(*mDispatcher,
9232 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9233 AINPUT_SOURCE_TOUCHSCREEN)
9234 .pointer(PointerBuilder(0, ToolType::FINGER)
9235 .x(FOCUSED_WINDOW_LOCATION.x)
9236 .y(FOCUSED_WINDOW_LOCATION.y))
9237 .build()));
9238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9239 injectMotionEvent(*mDispatcher,
9240 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9241 AINPUT_SOURCE_TOUCHSCREEN)
9242 .pointer(PointerBuilder(0, ToolType::FINGER)
9243 .x(FOCUSED_WINDOW_LOCATION.x)
9244 .y(FOCUSED_WINDOW_LOCATION.y))
9245 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009246 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009247 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009248 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009249 // We consumed all events, so no ANR
9250 ASSERT_TRUE(mDispatcher->waitForIdle());
9251 mFakePolicy->assertNotifyAnrWasNotCalled();
9252
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009254 injectMotionEvent(*mDispatcher,
9255 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9256 AINPUT_SOURCE_TOUCHSCREEN)
9257 .pointer(PointerBuilder(0, ToolType::FINGER)
9258 .x(FOCUSED_WINDOW_LOCATION.x)
9259 .y(FOCUSED_WINDOW_LOCATION.y))
9260 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009261 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009262 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009263
9264 const std::chrono::duration timeout =
9265 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009266 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009267
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009268 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009269 mFocusedWindow->consumeMotionDown();
9270 // This cancel is generated because the connection was unresponsive
9271 mFocusedWindow->consumeMotionCancel();
9272 mFocusedWindow->assertNoEvents();
9273 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009274 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009275 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9276 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009277 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009278}
9279
9280// If we have 2 windows with identical timeouts that are both unresponsive,
9281// it doesn't matter which order they should have ANR.
9282// But we should receive ANR for both.
9283TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9284 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009285 mUnfocusedWindow->setDispatchingTimeout(
9286 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009287 mDispatcher->onWindowInfosChanged(
9288 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009289
9290 tapOnFocusedWindow();
9291 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009292 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009293 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9294 mFocusedWindow->getDispatchingTimeout(
9295 DISPATCHING_TIMEOUT)),
9296 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9297
9298 ASSERT_THAT(anrConnectionTokens,
9299 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9300 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009301
9302 ASSERT_TRUE(mDispatcher->waitForIdle());
9303 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009304
9305 mFocusedWindow->consumeMotionDown();
9306 mFocusedWindow->consumeMotionUp();
9307 mUnfocusedWindow->consumeMotionOutside();
9308
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009309 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9310 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009311
9312 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009313 ASSERT_THAT(responsiveTokens,
9314 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9315 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009316 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009317}
9318
9319// If a window is already not responding, the second tap on the same window should be ignored.
9320// We should also log an error to account for the dropped event (not tested here).
9321// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9322TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9323 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009324 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009325 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009326 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009327 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009328 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009329 ASSERT_TRUE(upEventSequenceNum);
9330 const std::chrono::duration timeout =
9331 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009332 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009333
9334 // Tap once again
9335 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009336 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009337 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009338 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009339 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009340 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009341 FOCUSED_WINDOW_LOCATION));
9342 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9343 // valid touch target
9344 mUnfocusedWindow->assertNoEvents();
9345
9346 // Consume the first tap
9347 mFocusedWindow->finishEvent(*downEventSequenceNum);
9348 mFocusedWindow->finishEvent(*upEventSequenceNum);
9349 ASSERT_TRUE(mDispatcher->waitForIdle());
9350 // The second tap did not go to the focused window
9351 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009352 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009353 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9354 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009355 mFakePolicy->assertNotifyAnrWasNotCalled();
9356}
9357
9358// If you tap outside of all windows, there will not be ANR
9359TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009360 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009362 LOCATION_OUTSIDE_ALL_WINDOWS));
9363 ASSERT_TRUE(mDispatcher->waitForIdle());
9364 mFakePolicy->assertNotifyAnrWasNotCalled();
9365}
9366
9367// Since the focused window is paused, tapping on it should not produce any events
9368TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9369 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009370 mDispatcher->onWindowInfosChanged(
9371 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009372
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009373 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009374 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009375 FOCUSED_WINDOW_LOCATION));
9376
9377 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9378 ASSERT_TRUE(mDispatcher->waitForIdle());
9379 // Should not ANR because the window is paused, and touches shouldn't go to it
9380 mFakePolicy->assertNotifyAnrWasNotCalled();
9381
9382 mFocusedWindow->assertNoEvents();
9383 mUnfocusedWindow->assertNoEvents();
9384}
9385
9386/**
9387 * If a window is processing a motion event, and then a key event comes in, the key event should
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009388 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009389 * If a different window becomes focused at this time, the key should go to that window instead.
9390 *
9391 * Warning!!!
9392 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9393 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009394 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009395 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9396 *
9397 * If that value changes, this test should also change.
9398 */
9399TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9400 // Set a long ANR timeout to prevent it from triggering
9401 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009402 mDispatcher->onWindowInfosChanged(
9403 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009404
9405 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009406 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009407 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009408 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009409 ASSERT_TRUE(upSequenceNum);
9410 // Don't finish the events yet, and send a key
9411 // Injection will succeed because we will eventually give up and send the key to the focused
9412 // window even if motions are still being processed.
9413
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009414 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009415 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9416 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009418 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009419 // and the key remains pending, waiting for the touch events to be processed.
9420 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9421 // under the hood.
9422 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9423 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009424
9425 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009426 mFocusedWindow->setFocusable(false);
9427 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009428 mDispatcher->onWindowInfosChanged(
9429 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009430 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009431
9432 // Focus events should precede the key events
9433 mUnfocusedWindow->consumeFocusEvent(true);
9434 mFocusedWindow->consumeFocusEvent(false);
9435
9436 // Finish the tap events, which should unblock dispatcher
9437 mUnfocusedWindow->finishEvent(*downSequenceNum);
9438 mUnfocusedWindow->finishEvent(*upSequenceNum);
9439
9440 // Now that all queues are cleared and no backlog in the connections, the key event
9441 // can finally go to the newly focused "mUnfocusedWindow".
9442 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9443 mFocusedWindow->assertNoEvents();
9444 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009445 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009446}
9447
9448// When the touch stream is split across 2 windows, and one of them does not respond,
9449// then ANR should be raised and the touch should be canceled for the unresponsive window.
9450// The other window should not be affected by that.
9451TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9452 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009453 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9454 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9455 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009456 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009457
9458 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009459 mDispatcher->notifyMotion(
9460 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9461 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009462
9463 const std::chrono::duration timeout =
9464 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009465 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009466
9467 mUnfocusedWindow->consumeMotionDown();
9468 mFocusedWindow->consumeMotionDown();
9469 // Focused window may or may not receive ACTION_MOVE
9470 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009471 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009472 ASSERT_TRUE(moveOrCancelSequenceNum);
9473 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9474 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009475 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009476 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9477 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9478 mFocusedWindow->consumeMotionCancel();
9479 } else {
9480 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9481 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009482 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009483 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9484 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009485
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009486 mUnfocusedWindow->assertNoEvents();
9487 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009488 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009489}
9490
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009491/**
9492 * If we have no focused window, and a key comes in, we start the ANR timer.
9493 * The focused application should add a focused window before the timer runs out to prevent ANR.
9494 *
9495 * If the user touches another application during this time, the key should be dropped.
9496 * Next, if a new focused window comes in, without toggling the focused application,
9497 * then no ANR should occur.
9498 *
9499 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9500 * but in some cases the policy may not update the focused application.
9501 */
9502TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9503 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9504 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009505 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009506 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9507 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9508 mFocusedWindow->setFocusable(false);
9509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009510 mDispatcher->onWindowInfosChanged(
9511 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009512 mFocusedWindow->consumeFocusEvent(false);
9513
9514 // Send a key. The ANR timer should start because there is no focused window.
9515 // 'focusedApplication' will get blamed if this timer completes.
9516 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009517 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009518 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9519 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009520 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009522
9523 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9524 // then the injected touches won't cause the focused event to get dropped.
9525 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9526 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9527 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9528 // For this test, it means that the key would get delivered to the window once it becomes
9529 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009530 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009531
9532 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009533 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9534 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9535 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009536
9537 // We do not consume the motion right away, because that would require dispatcher to first
9538 // process (== drop) the key event, and by that time, ANR will be raised.
9539 // Set the focused window first.
9540 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009541 mDispatcher->onWindowInfosChanged(
9542 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009543 setFocusedWindow(mFocusedWindow);
9544 mFocusedWindow->consumeFocusEvent(true);
9545 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9546 // to another application. This could be a bug / behaviour in the policy.
9547
9548 mUnfocusedWindow->consumeMotionDown();
9549
9550 ASSERT_TRUE(mDispatcher->waitForIdle());
9551 // Should not ANR because we actually have a focused window. It was just added too slowly.
9552 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9553}
9554
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009555/**
9556 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9557 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9558 * dispatcher doesn't prune pointer events incorrectly.
9559 *
9560 * This test reproduces a crash in InputDispatcher.
9561 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9562 *
9563 * Keep the currently focused application (mApplication), and have no focused window.
9564 * We set up two additional windows:
9565 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9566 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9567 * window. This window is not focusable, but is touchable.
9568 *
9569 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9570 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9571 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9572 *
9573 * Now, we touch "Another window". This window is owned by a different application than
9574 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9575 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9576 * dropping the events from its queue. Ensure that no crash occurs.
9577 *
9578 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9579 * This does not affect the test running time.
9580 */
9581TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9582 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9583 std::make_shared<FakeApplicationHandle>();
9584 systemUiApplication->setDispatchingTimeout(3000ms);
9585 mFakePolicy->setStaleEventTimeout(3000ms);
9586 sp<FakeWindowHandle> navigationBar =
9587 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9588 ADISPLAY_ID_DEFAULT);
9589 navigationBar->setFocusable(false);
9590 navigationBar->setWatchOutsideTouch(true);
9591 navigationBar->setFrame(Rect(0, 0, 100, 100));
9592
9593 mApplication->setDispatchingTimeout(3000ms);
9594 // 'mApplication' is already focused, but we call it again here to make it explicit.
9595 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9596
9597 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9598 std::make_shared<FakeApplicationHandle>();
9599 sp<FakeWindowHandle> appWindow =
9600 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9601 ADISPLAY_ID_DEFAULT);
9602 appWindow->setFocusable(false);
9603 appWindow->setFrame(Rect(100, 100, 200, 200));
9604
9605 mDispatcher->onWindowInfosChanged(
9606 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9607 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9608 mFocusedWindow->consumeFocusEvent(false);
9609
9610 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9611 // in response.
9612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9613 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9614 .build());
9615 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9616
9617 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9618 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9619 InputEventInjectionResult result =
9620 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9621 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9622 /*allowKeyRepeat=*/false);
9623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9624
9625 // Finish the gesture - lift up finger and inject ACTION_UP key event
9626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9627 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9628 .build());
9629 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9630 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9631 /*allowKeyRepeat=*/false);
9632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9633 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9634 // getting any events yet.
9635 navigationBar->assertNoEvents();
9636
9637 // Now touch "Another window". This touch is going to a different application than the one we
9638 // are waiting for (which is 'mApplication').
9639 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9640 // trying to be injected) and to continue processing the rest of the events in the original
9641 // order.
9642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9643 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9644 .build());
9645 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9646 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9647 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9648
9649 appWindow->assertNoEvents();
9650 navigationBar->assertNoEvents();
9651}
9652
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009653// These tests ensure we cannot send touch events to a window that's positioned behind a window
9654// that has feature NO_INPUT_CHANNEL.
9655// Layout:
9656// Top (closest to user)
9657// mNoInputWindow (above all windows)
9658// mBottomWindow
9659// Bottom (furthest from user)
9660class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9661 virtual void SetUp() override {
9662 InputDispatcherTest::SetUp();
9663
9664 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009665 mNoInputWindow =
9666 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9667 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009668 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009669 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009670 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9671 // It's perfectly valid for this window to not have an associated input channel
9672
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009673 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9674 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009675 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009677 mDispatcher->onWindowInfosChanged(
9678 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009679 }
9680
9681protected:
9682 std::shared_ptr<FakeApplicationHandle> mApplication;
9683 sp<FakeWindowHandle> mNoInputWindow;
9684 sp<FakeWindowHandle> mBottomWindow;
9685};
9686
9687TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9688 PointF touchedPoint = {10, 10};
9689
Prabir Pradhan678438e2023-04-13 19:32:51 +00009690 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9691 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9692 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009693
9694 mNoInputWindow->assertNoEvents();
9695 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9696 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9697 // and therefore should prevent mBottomWindow from receiving touches
9698 mBottomWindow->assertNoEvents();
9699}
9700
9701/**
9702 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9703 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9704 */
9705TEST_F(InputDispatcherMultiWindowOcclusionTests,
9706 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009707 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9708 "Window with input channel and NO_INPUT_CHANNEL",
9709 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009710
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009711 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009712 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 mDispatcher->onWindowInfosChanged(
9714 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009715
9716 PointF touchedPoint = {10, 10};
9717
Prabir Pradhan678438e2023-04-13 19:32:51 +00009718 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9719 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9720 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009721
9722 mNoInputWindow->assertNoEvents();
9723 mBottomWindow->assertNoEvents();
9724}
9725
Vishnu Nair958da932020-08-21 17:12:37 -07009726class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9727protected:
9728 std::shared_ptr<FakeApplicationHandle> mApp;
9729 sp<FakeWindowHandle> mWindow;
9730 sp<FakeWindowHandle> mMirror;
9731
9732 virtual void SetUp() override {
9733 InputDispatcherTest::SetUp();
9734 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009735 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009736 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009737 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9738 mWindow->setFocusable(true);
9739 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009740 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009741 }
9742};
9743
9744TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9745 // Request focus on a mirrored window
9746 setFocusedWindow(mMirror);
9747
9748 // window gets focused
9749 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009751 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009752 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9753}
9754
9755// A focused & mirrored window remains focused only if the window and its mirror are both
9756// focusable.
9757TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9758 setFocusedWindow(mMirror);
9759
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009760 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009761 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009764 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009766 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009767 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9768
9769 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009770 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009771
9772 // window loses focus since one of the windows associated with the token in not focusable
9773 mWindow->consumeFocusEvent(false);
9774
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009775 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009776 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009777 mWindow->assertNoEvents();
9778}
9779
9780// A focused & mirrored window remains focused until the window and its mirror both become
9781// invisible.
9782TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9783 setFocusedWindow(mMirror);
9784
9785 // window gets focused
9786 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009788 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009789 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009792 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9793
9794 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009795 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009796
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009798 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009799 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009801 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009802 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9803
9804 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009805 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009806
9807 // window loses focus only after all windows associated with the token become invisible.
9808 mWindow->consumeFocusEvent(false);
9809
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009810 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009811 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009812 mWindow->assertNoEvents();
9813}
9814
9815// A focused & mirrored window remains focused until both windows are removed.
9816TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9817 setFocusedWindow(mMirror);
9818
9819 // window gets focused
9820 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009822 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009823 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009825 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009826 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9827
9828 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009829 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009830
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009832 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009833 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009835 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009836 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009837
9838 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009839 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009840 mWindow->consumeFocusEvent(false);
9841
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009842 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009843 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009844 mWindow->assertNoEvents();
9845}
9846
9847// Focus request can be pending until one window becomes visible.
9848TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9849 // Request focus on an invisible mirror.
9850 mWindow->setVisible(false);
9851 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009852 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009853 setFocusedWindow(mMirror);
9854
9855 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009857 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9858 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009859
9860 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009861 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009862
9863 // window gets focused
9864 mWindow->consumeFocusEvent(true);
9865 // window gets the pending key event
9866 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9867}
Prabir Pradhan99987712020-11-10 18:43:05 -08009868
9869class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9870protected:
9871 std::shared_ptr<FakeApplicationHandle> mApp;
9872 sp<FakeWindowHandle> mWindow;
9873 sp<FakeWindowHandle> mSecondWindow;
9874
9875 void SetUp() override {
9876 InputDispatcherTest::SetUp();
9877 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009878 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009879 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009880 mSecondWindow =
9881 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009882 mSecondWindow->setFocusable(true);
9883
9884 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009885 mDispatcher->onWindowInfosChanged(
9886 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009887
9888 setFocusedWindow(mWindow);
9889 mWindow->consumeFocusEvent(true);
9890 }
9891
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009892 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009893 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009894 }
9895
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009896 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9897 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009898 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +09009899 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009900 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009901 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009902 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009903 }
9904};
9905
9906TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9907 // Ensure that capture cannot be obtained for unfocused windows.
9908 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9909 mFakePolicy->assertSetPointerCaptureNotCalled();
9910 mSecondWindow->assertNoEvents();
9911
9912 // Ensure that capture can be enabled from the focus window.
9913 requestAndVerifyPointerCapture(mWindow, true);
9914
9915 // Ensure that capture cannot be disabled from a window that does not have capture.
9916 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9917 mFakePolicy->assertSetPointerCaptureNotCalled();
9918
9919 // Ensure that capture can be disabled from the window with capture.
9920 requestAndVerifyPointerCapture(mWindow, false);
9921}
9922
9923TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009924 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009925
9926 setFocusedWindow(mSecondWindow);
9927
9928 // Ensure that the capture disabled event was sent first.
9929 mWindow->consumeCaptureEvent(false);
9930 mWindow->consumeFocusEvent(false);
9931 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +09009932 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009933
9934 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009935 notifyPointerCaptureChanged({});
9936 notifyPointerCaptureChanged(request);
9937 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009938 mWindow->assertNoEvents();
9939 mSecondWindow->assertNoEvents();
9940 mFakePolicy->assertSetPointerCaptureNotCalled();
9941}
9942
9943TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009944 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009945
9946 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009947 notifyPointerCaptureChanged({});
9948 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009949
9950 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009951 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009952 mWindow->consumeCaptureEvent(false);
9953 mWindow->assertNoEvents();
9954}
9955
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009956TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9957 requestAndVerifyPointerCapture(mWindow, true);
9958
9959 // The first window loses focus.
9960 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +09009961 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009962 mWindow->consumeCaptureEvent(false);
9963
9964 // Request Pointer Capture from the second window before the notification from InputReader
9965 // arrives.
9966 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009967 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009968
9969 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009970 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009971
9972 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009973 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009974
9975 mSecondWindow->consumeFocusEvent(true);
9976 mSecondWindow->consumeCaptureEvent(true);
9977}
9978
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009979TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9980 // App repeatedly enables and disables capture.
9981 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009982 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009983 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +09009984 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009985 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009986 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009987
9988 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9989 // first request is now stale, this should do nothing.
9990 notifyPointerCaptureChanged(firstRequest);
9991 mWindow->assertNoEvents();
9992
9993 // InputReader notifies that the second request was enabled.
9994 notifyPointerCaptureChanged(secondRequest);
9995 mWindow->consumeCaptureEvent(true);
9996}
9997
Prabir Pradhan7092e262022-05-03 16:51:09 +00009998TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9999 requestAndVerifyPointerCapture(mWindow, true);
10000
10001 // App toggles pointer capture off and on.
10002 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010003 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010004
10005 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010006 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010007
10008 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10009 // preceding "disable" request.
10010 notifyPointerCaptureChanged(enableRequest);
10011
10012 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10013 // any notifications.
10014 mWindow->assertNoEvents();
10015}
10016
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010017/**
10018 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10019 * mouse movements don't affect the previous mouse hovering state.
10020 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10021 * HOVER_MOVE events).
10022 */
10023TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10024 // Mouse hover on the window
10025 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10027 .build());
10028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10029 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10030 .build());
10031
10032 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10033 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10034
10035 // Start pointer capture
10036 requestAndVerifyPointerCapture(mWindow, true);
10037
10038 // Send some relative mouse movements and receive them in the window.
10039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10040 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10041 .build());
10042 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10043 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10044
10045 // Stop pointer capture
10046 requestAndVerifyPointerCapture(mWindow, false);
10047
10048 // Continue hovering on the window
10049 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10050 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10051 .build());
10052 mWindow->consumeMotionEvent(
10053 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10054
10055 mWindow->assertNoEvents();
10056}
10057
Hiroki Sato25040232024-02-22 17:21:22 +090010058using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
10059
10060TEST_F(InputDispatcherPointerCaptureDeathTest,
10061 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
10062 testing::GTEST_FLAG(death_test_style) = "threadsafe";
10063 ScopedSilentDeath _silentDeath;
10064
10065 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10066 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
10067
10068 // Dispatch a pointer changed event with a wrong token.
10069 request.window = mSecondWindow->getToken();
10070 ASSERT_DEATH(
10071 {
10072 notifyPointerCaptureChanged(request);
10073 mSecondWindow->consumeCaptureEvent(true);
10074 },
10075 "Unexpected requested window for Pointer Capture.");
10076}
10077
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010078class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10079protected:
10080 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010081
10082 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10083 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10084
10085 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10086 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10087
10088 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10089 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10090 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10091 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10092 MAXIMUM_OBSCURING_OPACITY);
10093
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010094 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10095 static constexpr gui::Uid APP_B_UID{10002};
10096 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010097
10098 sp<FakeWindowHandle> mTouchWindow;
10099
10100 virtual void SetUp() override {
10101 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010102 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010103 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10104 }
10105
10106 virtual void TearDown() override {
10107 InputDispatcherTest::TearDown();
10108 mTouchWindow.clear();
10109 }
10110
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010111 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010112 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010113 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010114 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010115 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010116 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010117 return window;
10118 }
10119
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010120 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010121 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10122 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010123 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010124 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010125 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010126 return window;
10127 }
10128
10129 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010130 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10131 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10132 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010133 }
10134};
10135
10136TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010137 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010138 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010139 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010140
10141 touch();
10142
10143 mTouchWindow->assertNoEvents();
10144}
10145
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010146TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010147 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10148 const sp<FakeWindowHandle>& w =
10149 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010150 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010151
10152 touch();
10153
10154 mTouchWindow->assertNoEvents();
10155}
10156
10157TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010158 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10159 const sp<FakeWindowHandle>& w =
10160 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010161 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010162
10163 touch();
10164
10165 w->assertNoEvents();
10166}
10167
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010168TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010169 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010170 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010171
10172 touch();
10173
10174 mTouchWindow->consumeAnyMotionDown();
10175}
10176
10177TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010178 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010179 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010180 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010181 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010182
10183 touch({PointF{100, 100}});
10184
10185 mTouchWindow->consumeAnyMotionDown();
10186}
10187
10188TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010189 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010190 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010191 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010192
10193 touch();
10194
10195 mTouchWindow->consumeAnyMotionDown();
10196}
10197
10198TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10199 const sp<FakeWindowHandle>& w =
10200 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010201 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010202
10203 touch();
10204
10205 mTouchWindow->consumeAnyMotionDown();
10206}
10207
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010208TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10209 const sp<FakeWindowHandle>& w =
10210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010211 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010212
10213 touch();
10214
10215 w->assertNoEvents();
10216}
10217
10218/**
10219 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10220 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10221 * window, the occluding window will still receive ACTION_OUTSIDE event.
10222 */
10223TEST_F(InputDispatcherUntrustedTouchesTest,
10224 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10225 const sp<FakeWindowHandle>& w =
10226 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010227 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010228 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010229
10230 touch();
10231
10232 w->consumeMotionOutside();
10233}
10234
10235TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10236 const sp<FakeWindowHandle>& w =
10237 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010238 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010239 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010240
10241 touch();
10242
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010243 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010244}
10245
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010246TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010247 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010248 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10249 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010250 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010251
10252 touch();
10253
10254 mTouchWindow->consumeAnyMotionDown();
10255}
10256
10257TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10258 const sp<FakeWindowHandle>& w =
10259 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10260 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010261 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010262
10263 touch();
10264
10265 mTouchWindow->consumeAnyMotionDown();
10266}
10267
10268TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010269 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010270 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10271 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010272 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010273
10274 touch();
10275
10276 mTouchWindow->assertNoEvents();
10277}
10278
10279TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10280 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10281 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010282 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10283 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010284 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010285 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10286 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010287 mDispatcher->onWindowInfosChanged(
10288 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010289
10290 touch();
10291
10292 mTouchWindow->assertNoEvents();
10293}
10294
10295TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10296 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10297 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010298 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10299 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010300 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010301 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10302 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010303 mDispatcher->onWindowInfosChanged(
10304 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010305
10306 touch();
10307
10308 mTouchWindow->consumeAnyMotionDown();
10309}
10310
10311TEST_F(InputDispatcherUntrustedTouchesTest,
10312 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10313 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010314 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10315 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010316 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010317 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10318 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010319 mDispatcher->onWindowInfosChanged(
10320 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010321
10322 touch();
10323
10324 mTouchWindow->consumeAnyMotionDown();
10325}
10326
10327TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10328 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010329 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10330 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010331 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010332 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10333 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010334 mDispatcher->onWindowInfosChanged(
10335 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010336
10337 touch();
10338
10339 mTouchWindow->assertNoEvents();
10340}
10341
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010342TEST_F(InputDispatcherUntrustedTouchesTest,
10343 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10344 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010345 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10346 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010347 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010348 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10349 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010350 mDispatcher->onWindowInfosChanged(
10351 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010352
10353 touch();
10354
10355 mTouchWindow->assertNoEvents();
10356}
10357
10358TEST_F(InputDispatcherUntrustedTouchesTest,
10359 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10360 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010361 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10362 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010363 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010364 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10365 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010366 mDispatcher->onWindowInfosChanged(
10367 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010368
10369 touch();
10370
10371 mTouchWindow->consumeAnyMotionDown();
10372}
10373
10374TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10375 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010376 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10377 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010378 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010379
10380 touch();
10381
10382 mTouchWindow->consumeAnyMotionDown();
10383}
10384
10385TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10386 const sp<FakeWindowHandle>& w =
10387 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010388 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010389
10390 touch();
10391
10392 mTouchWindow->consumeAnyMotionDown();
10393}
10394
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010395TEST_F(InputDispatcherUntrustedTouchesTest,
10396 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10397 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10398 const sp<FakeWindowHandle>& w =
10399 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010400 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010401
10402 touch();
10403
10404 mTouchWindow->assertNoEvents();
10405}
10406
10407TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10408 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10409 const sp<FakeWindowHandle>& w =
10410 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010411 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010412
10413 touch();
10414
10415 mTouchWindow->consumeAnyMotionDown();
10416}
10417
10418TEST_F(InputDispatcherUntrustedTouchesTest,
10419 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10420 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10421 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010422 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10423 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010424 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010425
10426 touch();
10427
10428 mTouchWindow->consumeAnyMotionDown();
10429}
10430
10431TEST_F(InputDispatcherUntrustedTouchesTest,
10432 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10433 const sp<FakeWindowHandle>& w1 =
10434 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10435 OPACITY_BELOW_THRESHOLD);
10436 const sp<FakeWindowHandle>& w2 =
10437 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10438 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010439 mDispatcher->onWindowInfosChanged(
10440 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010441
10442 touch();
10443
10444 mTouchWindow->assertNoEvents();
10445}
10446
10447/**
10448 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10449 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10450 * (which alone would result in allowing touches) does not affect the blocking behavior.
10451 */
10452TEST_F(InputDispatcherUntrustedTouchesTest,
10453 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10454 const sp<FakeWindowHandle>& wB =
10455 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10456 OPACITY_BELOW_THRESHOLD);
10457 const sp<FakeWindowHandle>& wC =
10458 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10459 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010460 mDispatcher->onWindowInfosChanged(
10461 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010462
10463 touch();
10464
10465 mTouchWindow->assertNoEvents();
10466}
10467
10468/**
10469 * This test is testing that a window from a different UID but with same application token doesn't
10470 * block the touch. Apps can share the application token for close UI collaboration for example.
10471 */
10472TEST_F(InputDispatcherUntrustedTouchesTest,
10473 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10474 const sp<FakeWindowHandle>& w =
10475 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10476 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010477 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010478
10479 touch();
10480
10481 mTouchWindow->consumeAnyMotionDown();
10482}
10483
arthurhungb89ccb02020-12-30 16:19:01 +080010484class InputDispatcherDragTests : public InputDispatcherTest {
10485protected:
10486 std::shared_ptr<FakeApplicationHandle> mApp;
10487 sp<FakeWindowHandle> mWindow;
10488 sp<FakeWindowHandle> mSecondWindow;
10489 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010490 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010491 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10492 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010493
10494 void SetUp() override {
10495 InputDispatcherTest::SetUp();
10496 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010497 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010498 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010499
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010500 mSecondWindow =
10501 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010502 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010503
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010504 mSpyWindow =
10505 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010506 mSpyWindow->setSpy(true);
10507 mSpyWindow->setTrustedOverlay(true);
10508 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10509
arthurhungb89ccb02020-12-30 16:19:01 +080010510 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010511 mDispatcher->onWindowInfosChanged(
10512 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10513 {},
10514 0,
10515 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010516 }
10517
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010518 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10519 switch (fromSource) {
10520 case AINPUT_SOURCE_TOUCHSCREEN:
10521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010522 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010523 ADISPLAY_ID_DEFAULT, {50, 50}))
10524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10525 break;
10526 case AINPUT_SOURCE_STYLUS:
10527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010528 injectMotionEvent(*mDispatcher,
10529 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10530 AINPUT_SOURCE_STYLUS)
10531 .buttonState(
10532 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10533 .pointer(PointerBuilder(0, ToolType::STYLUS)
10534 .x(50)
10535 .y(50))
10536 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010537 break;
10538 case AINPUT_SOURCE_MOUSE:
10539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010540 injectMotionEvent(*mDispatcher,
10541 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10542 AINPUT_SOURCE_MOUSE)
10543 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10544 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10545 ToolType::MOUSE)
10546 .x(50)
10547 .y(50))
10548 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010549 break;
10550 default:
10551 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10552 }
arthurhungb89ccb02020-12-30 16:19:01 +080010553
10554 // Window should receive motion event.
10555 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010556 // Spy window should also receive motion event
10557 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010558 }
10559
10560 // Start performing drag, we will create a drag window and transfer touch to it.
10561 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10562 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010563 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010564 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010565 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010566 }
arthurhungb89ccb02020-12-30 16:19:01 +080010567
10568 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010569 mDragWindow =
10570 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010571 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010572 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10573 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10574 {},
10575 0,
10576 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010577
10578 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010579 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010580 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10581 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010582 if (transferred) {
10583 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010584 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010585 }
10586 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010587 }
10588};
10589
10590TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010591 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010592
10593 // Move on window.
10594 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010595 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010596 ADISPLAY_ID_DEFAULT, {50, 50}))
10597 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010598 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010599 mWindow->consumeDragEvent(false, 50, 50);
10600 mSecondWindow->assertNoEvents();
10601
10602 // Move to another window.
10603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010604 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010605 ADISPLAY_ID_DEFAULT, {150, 50}))
10606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010607 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010608 mWindow->consumeDragEvent(true, 150, 50);
10609 mSecondWindow->consumeDragEvent(false, 50, 50);
10610
10611 // Move back to original window.
10612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010613 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010614 ADISPLAY_ID_DEFAULT, {50, 50}))
10615 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010616 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010617 mWindow->consumeDragEvent(false, 50, 50);
10618 mSecondWindow->consumeDragEvent(true, -50, 50);
10619
10620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010621 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10622 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010624 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010625 mWindow->assertNoEvents();
10626 mSecondWindow->assertNoEvents();
10627}
10628
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010629TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010630 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010631
10632 // No cancel event after drag start
10633 mSpyWindow->assertNoEvents();
10634
10635 const MotionEvent secondFingerDownEvent =
10636 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10637 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010638 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10639 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010640 .build();
10641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010642 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010643 InputEventInjectionSync::WAIT_FOR_RESULT))
10644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10645
10646 // Receives cancel for first pointer after next pointer down
10647 mSpyWindow->consumeMotionCancel();
10648 mSpyWindow->consumeMotionDown();
10649
10650 mSpyWindow->assertNoEvents();
10651}
10652
arthurhungf452d0b2021-01-06 00:19:52 +080010653TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010654 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010655
10656 // Move on window.
10657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010659 ADISPLAY_ID_DEFAULT, {50, 50}))
10660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010661 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010662 mWindow->consumeDragEvent(false, 50, 50);
10663 mSecondWindow->assertNoEvents();
10664
10665 // Move to another window.
10666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010667 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010668 ADISPLAY_ID_DEFAULT, {150, 50}))
10669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010670 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010671 mWindow->consumeDragEvent(true, 150, 50);
10672 mSecondWindow->consumeDragEvent(false, 50, 50);
10673
10674 // drop to another window.
10675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010676 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010677 {150, 50}))
10678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010679 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010680 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010681 mWindow->assertNoEvents();
10682 mSecondWindow->assertNoEvents();
10683}
10684
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010685TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10686 startDrag();
10687
10688 // No cancel event after drag start
10689 mSpyWindow->assertNoEvents();
10690
10691 const MotionEvent secondFingerDownEvent =
10692 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10693 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10694 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10695 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10696 .build();
10697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10698 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10699 InputEventInjectionSync::WAIT_FOR_RESULT))
10700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10701
10702 // Receives cancel for first pointer after next pointer down
10703 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010704 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010705 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10706
10707 mSpyWindow->assertNoEvents();
10708
10709 // Spy window calls pilfer pointers
10710 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10711 mDragWindow->assertNoEvents();
10712
10713 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010714 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010715 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10716 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10717 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10718 .build();
10719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010720 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010721 InputEventInjectionSync::WAIT_FOR_RESULT))
10722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10723
10724 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010725 mDragWindow->consumeMotionEvent(
10726 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010727 mDragWindow->assertNoEvents();
10728}
10729
arthurhung6d4bed92021-03-17 11:59:33 +080010730TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010731 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010732
10733 // Move on window and keep button pressed.
10734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010735 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010736 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10737 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010739 .build()))
10740 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010741 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010742 mWindow->consumeDragEvent(false, 50, 50);
10743 mSecondWindow->assertNoEvents();
10744
10745 // Move to another window and release button, expect to drop item.
10746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010747 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010748 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10749 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010750 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010751 .build()))
10752 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010753 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010754 mWindow->assertNoEvents();
10755 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010756 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010757
10758 // nothing to the window.
10759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010760 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010761 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10762 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010763 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010764 .build()))
10765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010766 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010767 mWindow->assertNoEvents();
10768 mSecondWindow->assertNoEvents();
10769}
10770
Arthur Hung54745652022-04-20 07:17:41 +000010771TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010772 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010773
10774 // Set second window invisible.
10775 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010776 mDispatcher->onWindowInfosChanged(
10777 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010778
10779 // Move on window.
10780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010781 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010782 ADISPLAY_ID_DEFAULT, {50, 50}))
10783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010784 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010785 mWindow->consumeDragEvent(false, 50, 50);
10786 mSecondWindow->assertNoEvents();
10787
10788 // Move to another window.
10789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010790 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010791 ADISPLAY_ID_DEFAULT, {150, 50}))
10792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010793 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010794 mWindow->consumeDragEvent(true, 150, 50);
10795 mSecondWindow->assertNoEvents();
10796
10797 // drop to another window.
10798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010799 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010800 {150, 50}))
10801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010802 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010803 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010804 mWindow->assertNoEvents();
10805 mSecondWindow->assertNoEvents();
10806}
10807
Arthur Hung54745652022-04-20 07:17:41 +000010808TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010809 // Ensure window could track pointerIds if it didn't support split touch.
10810 mWindow->setPreventSplitting(true);
10811
Arthur Hung54745652022-04-20 07:17:41 +000010812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010813 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010814 {50, 50}))
10815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10816 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10817
10818 const MotionEvent secondFingerDownEvent =
10819 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10820 .displayId(ADISPLAY_ID_DEFAULT)
10821 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010822 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10823 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010824 .build();
10825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010826 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010827 InputEventInjectionSync::WAIT_FOR_RESULT))
10828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010829 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010830
10831 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010832 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010833}
10834
10835TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10836 // First down on second window.
10837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010838 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010839 {150, 50}))
10840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10841
10842 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10843
10844 // Second down on first window.
10845 const MotionEvent secondFingerDownEvent =
10846 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10847 .displayId(ADISPLAY_ID_DEFAULT)
10848 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010849 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10850 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010851 .build();
10852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010853 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010854 InputEventInjectionSync::WAIT_FOR_RESULT))
10855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10856 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010857 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010858
10859 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010860 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010861
10862 // Move on window.
10863 const MotionEvent secondFingerMoveEvent =
10864 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10865 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010866 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10867 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010868 .build();
10869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010870 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010871 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010872 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010873 mWindow->consumeDragEvent(false, 50, 50);
10874 mSecondWindow->consumeMotionMove();
10875
10876 // Release the drag pointer should perform drop.
10877 const MotionEvent secondFingerUpEvent =
10878 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10879 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010880 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10881 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010882 .build();
10883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010884 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010885 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010886 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010887 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010888 mWindow->assertNoEvents();
10889 mSecondWindow->consumeMotionMove();
10890}
10891
Arthur Hung3915c1f2022-05-31 07:17:17 +000010892TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010893 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010894
10895 // Update window of second display.
10896 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010897 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010898 mDispatcher->onWindowInfosChanged(
10899 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10900 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10901 {},
10902 0,
10903 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010904
10905 // Let second display has a touch state.
10906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010907 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010908 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10909 AINPUT_SOURCE_TOUCHSCREEN)
10910 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010911 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010912 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010913 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010914 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010915 mDispatcher->onWindowInfosChanged(
10916 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10917 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10918 {},
10919 0,
10920 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010921
10922 // Move on window.
10923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010924 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010925 ADISPLAY_ID_DEFAULT, {50, 50}))
10926 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010927 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010928 mWindow->consumeDragEvent(false, 50, 50);
10929 mSecondWindow->assertNoEvents();
10930
10931 // Move to another window.
10932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010933 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010934 ADISPLAY_ID_DEFAULT, {150, 50}))
10935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010936 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010937 mWindow->consumeDragEvent(true, 150, 50);
10938 mSecondWindow->consumeDragEvent(false, 50, 50);
10939
10940 // drop to another window.
10941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010942 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010943 {150, 50}))
10944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010945 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010946 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010947 mWindow->assertNoEvents();
10948 mSecondWindow->assertNoEvents();
10949}
10950
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010951TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10952 startDrag(true, AINPUT_SOURCE_MOUSE);
10953 // Move on window.
10954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010955 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010956 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10957 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010958 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010959 .x(50)
10960 .y(50))
10961 .build()))
10962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010963 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010964 mWindow->consumeDragEvent(false, 50, 50);
10965 mSecondWindow->assertNoEvents();
10966
10967 // Move to another window.
10968 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010969 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010970 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10971 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010972 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010973 .x(150)
10974 .y(50))
10975 .build()))
10976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010977 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010978 mWindow->consumeDragEvent(true, 150, 50);
10979 mSecondWindow->consumeDragEvent(false, 50, 50);
10980
10981 // drop to another window.
10982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010983 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010984 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10985 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010986 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010987 .x(150)
10988 .y(50))
10989 .build()))
10990 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010991 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010992 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010993 mWindow->assertNoEvents();
10994 mSecondWindow->assertNoEvents();
10995}
10996
Linnan Li5af92f92023-07-14 14:36:22 +080010997/**
10998 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10999 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
11000 */
11001TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
11002 // Down on second window
11003 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11004 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11005 {150, 50}))
11006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11007
11008 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
11009 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
11010
11011 // Down on first window
11012 const MotionEvent secondFingerDownEvent =
11013 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11014 .displayId(ADISPLAY_ID_DEFAULT)
11015 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11016 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11017 .build();
11018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11019 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11020 InputEventInjectionSync::WAIT_FOR_RESULT))
11021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11022 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11023 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
11024 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
11025
11026 // Start drag on first window
11027 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11028
11029 // Trigger cancel
11030 mDispatcher->cancelCurrentTouch();
11031 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011032 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11033 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011034 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11035
11036 ASSERT_TRUE(mDispatcher->waitForIdle());
11037 // The D&D finished with nullptr
11038 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11039
11040 // Remove drag window
11041 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11042
11043 // Inject a simple gesture, ensure dispatcher not crashed
11044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11045 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11046 PointF{50, 50}))
11047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11048 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11049
11050 const MotionEvent moveEvent =
11051 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11052 .displayId(ADISPLAY_ID_DEFAULT)
11053 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11054 .build();
11055 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11056 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11057 InputEventInjectionSync::WAIT_FOR_RESULT))
11058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11059 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11060
11061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11062 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11063 {50, 50}))
11064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11065 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11066}
11067
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011068TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11069 // Start hovering over the window.
11070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11071 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11072 ADISPLAY_ID_DEFAULT, {50, 50}));
11073
11074 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11075 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11076
11077 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11078 << "Drag and drop should not work with a hovering pointer";
11079}
11080
Vishnu Nair062a8672021-09-03 16:07:44 -070011081class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11082
11083TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11084 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011085 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11086 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011087 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011088 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11089 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011091 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011092 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011093
11094 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011095 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011096 window->assertNoEvents();
11097
Prabir Pradhan678438e2023-04-13 19:32:51 +000011098 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11099 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011100 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11101 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011102 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011103 window->assertNoEvents();
11104
11105 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011106 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011107 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011108
Prabir Pradhan678438e2023-04-13 19:32:51 +000011109 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011110 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11111
Prabir Pradhan678438e2023-04-13 19:32:51 +000011112 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11113 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011114 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11115 window->assertNoEvents();
11116}
11117
11118TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11119 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11120 std::make_shared<FakeApplicationHandle>();
11121 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011122 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11123 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011124 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011125 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011126 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011128 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11129 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011130 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011131 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011132 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11133 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011134 mDispatcher->onWindowInfosChanged(
11135 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011136 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011137 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011138
11139 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011140 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011141 window->assertNoEvents();
11142
Prabir Pradhan678438e2023-04-13 19:32:51 +000011143 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11144 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11146 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011147 window->assertNoEvents();
11148
11149 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011150 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011151 mDispatcher->onWindowInfosChanged(
11152 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011153
Prabir Pradhan678438e2023-04-13 19:32:51 +000011154 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011155 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11156
Prabir Pradhan678438e2023-04-13 19:32:51 +000011157 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11158 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011159 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11160 window->assertNoEvents();
11161}
11162
11163TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11164 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11165 std::make_shared<FakeApplicationHandle>();
11166 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011167 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11168 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011169 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011170 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011171 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11174 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011175 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011176 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011177 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11178 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011179 mDispatcher->onWindowInfosChanged(
11180 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011181 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011182 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011183
11184 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011185 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011186 window->assertNoEvents();
11187
Prabir Pradhan678438e2023-04-13 19:32:51 +000011188 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11189 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011190 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11191 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011192 window->assertNoEvents();
11193
11194 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011195 mDispatcher->onWindowInfosChanged(
11196 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011197
Prabir Pradhan678438e2023-04-13 19:32:51 +000011198 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011199 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11200
Prabir Pradhan678438e2023-04-13 19:32:51 +000011201 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11202 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011203 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11204 window->assertNoEvents();
11205}
11206
Antonio Kantekf16f2832021-09-28 04:39:20 +000011207class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11208protected:
11209 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011210 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011211 sp<FakeWindowHandle> mWindow;
11212 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011213 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011214
11215 void SetUp() override {
11216 InputDispatcherTest::SetUp();
11217
11218 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011219 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011220 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011221 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011222 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011223 mSecondWindow =
11224 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011225 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011226 mThirdWindow =
11227 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11228 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11229 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011230
11231 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011232 mDispatcher->onWindowInfosChanged(
11233 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11234 {},
11235 0,
11236 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011237 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011238 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011239
Antonio Kantek15beb512022-06-13 22:35:41 +000011240 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011241 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011242 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011243 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11244 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011245 mThirdWindow->assertNoEvents();
11246 }
11247
11248 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11249 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011250 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011251 SECOND_DISPLAY_ID)) {
11252 mWindow->assertNoEvents();
11253 mSecondWindow->assertNoEvents();
11254 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011255 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011256 }
11257
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011258 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011259 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011260 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11261 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011262 mWindow->consumeTouchModeEvent(inTouchMode);
11263 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011264 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011265 }
11266};
11267
Antonio Kantek26defcf2022-02-08 01:12:27 +000011268TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011269 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011270 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11271 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011272 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011273}
11274
Antonio Kantek26defcf2022-02-08 01:12:27 +000011275TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11276 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011277 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011278 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011279 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011280 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011281 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011282 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011283 mWindow->assertNoEvents();
11284 mSecondWindow->assertNoEvents();
11285}
11286
11287TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11288 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011289 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011290 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011291 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011292 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011293 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011294}
11295
Antonio Kantekf16f2832021-09-28 04:39:20 +000011296TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011297 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011298 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11299 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011300 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011301 mWindow->assertNoEvents();
11302 mSecondWindow->assertNoEvents();
11303}
11304
Antonio Kantek15beb512022-06-13 22:35:41 +000011305TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11306 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11307 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11308 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011309 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011310 mWindow->assertNoEvents();
11311 mSecondWindow->assertNoEvents();
11312 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11313}
11314
Antonio Kantek48710e42022-03-24 14:19:30 -070011315TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11316 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11318 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011319 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11320 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11321
11322 // Then remove focus.
11323 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011324 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011325
11326 // Assert that caller can switch touch mode by owning one of the last interacted window.
11327 const WindowInfo& windowInfo = *mWindow->getInfo();
11328 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11329 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011330 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011331}
11332
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011333class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11334public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011335 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011336 std::shared_ptr<FakeApplicationHandle> application =
11337 std::make_shared<FakeApplicationHandle>();
11338 std::string name = "Fake Spy ";
11339 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011340 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11341 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011342 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011343 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011344 return spy;
11345 }
11346
11347 sp<FakeWindowHandle> createForeground() {
11348 std::shared_ptr<FakeApplicationHandle> application =
11349 std::make_shared<FakeApplicationHandle>();
11350 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011351 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11352 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011353 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011354 return window;
11355 }
11356
11357private:
11358 int mSpyCount{0};
11359};
11360
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011361using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011362/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011363 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11364 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011365TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011366 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011367 ScopedSilentDeath _silentDeath;
11368
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011369 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011370 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011371 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011372 ".* not a trusted overlay");
11373}
11374
11375/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011376 * Input injection into a display with a spy window but no foreground windows should succeed.
11377 */
11378TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011379 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011380 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011381
11382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011383 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011384 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11385 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11386}
11387
11388/**
11389 * Verify the order in which different input windows receive events. The touched foreground window
11390 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11391 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11392 * receive events before ones belows it.
11393 *
11394 * Here, we set up a scenario with four windows in the following Z order from the top:
11395 * spy1, spy2, window, spy3.
11396 * We then inject an event and verify that the foreground "window" receives it first, followed by
11397 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11398 * window.
11399 */
11400TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11401 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011402 auto spy1 = createSpy();
11403 auto spy2 = createSpy();
11404 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011405 mDispatcher->onWindowInfosChanged(
11406 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011407 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11408 const size_t numChannels = channels.size();
11409
Michael Wright8e9a8562022-02-09 13:44:29 +000011410 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011411 if (!epollFd.ok()) {
11412 FAIL() << "Failed to create epoll fd";
11413 }
11414
11415 for (size_t i = 0; i < numChannels; i++) {
11416 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11417 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11418 FAIL() << "Failed to add fd to epoll";
11419 }
11420 }
11421
11422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011423 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11425
11426 std::vector<size_t> eventOrder;
11427 std::vector<struct epoll_event> events(numChannels);
11428 for (;;) {
11429 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11430 (100ms).count());
11431 if (nFds < 0) {
11432 FAIL() << "Failed to call epoll_wait";
11433 }
11434 if (nFds == 0) {
11435 break; // epoll_wait timed out
11436 }
11437 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011438 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011439 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011440 channels[i]->consumeMotionDown();
11441 }
11442 }
11443
11444 // Verify the order in which the events were received.
11445 EXPECT_EQ(3u, eventOrder.size());
11446 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11447 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11448 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11449}
11450
11451/**
11452 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11453 */
11454TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11455 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011456 auto spy = createSpy();
11457 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011458 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011459
11460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011461 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11463 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11464 spy->assertNoEvents();
11465}
11466
11467/**
11468 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11469 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11470 * to the window.
11471 */
11472TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11473 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011474 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011475 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011476 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011477
11478 // Inject an event outside the spy window's touchable region.
11479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011480 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011481 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11482 window->consumeMotionDown();
11483 spy->assertNoEvents();
11484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011485 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011486 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11487 window->consumeMotionUp();
11488 spy->assertNoEvents();
11489
11490 // Inject an event inside the spy window's touchable region.
11491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011492 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011493 {5, 10}))
11494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11495 window->consumeMotionDown();
11496 spy->consumeMotionDown();
11497}
11498
11499/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011500 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011501 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011502 */
11503TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11504 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011505 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011506 auto spy = createSpy();
11507 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011508 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011509 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011511
11512 // Inject an event outside the spy window's frame and touchable region.
11513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011515 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011516 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11517 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011518 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011519}
11520
11521/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011522 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11523 * pointers that are down within its bounds.
11524 */
11525TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11526 auto windowLeft = createForeground();
11527 windowLeft->setFrame({0, 0, 100, 200});
11528 auto windowRight = createForeground();
11529 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011530 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011531 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011532 mDispatcher->onWindowInfosChanged(
11533 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011534
11535 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011536 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011537 {50, 50}))
11538 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11539 windowLeft->consumeMotionDown();
11540 spy->consumeMotionDown();
11541
11542 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011543 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011544 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011545 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11546 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011547 .build();
11548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011549 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011550 InputEventInjectionSync::WAIT_FOR_RESULT))
11551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11552 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011553 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011554}
11555
11556/**
11557 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11558 * the spy should receive the second pointer with ACTION_DOWN.
11559 */
11560TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11561 auto window = createForeground();
11562 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011563 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011564 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011565 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011566
11567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011568 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011569 {50, 50}))
11570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11571 window->consumeMotionDown();
11572 spyRight->assertNoEvents();
11573
11574 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011575 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011576 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011579 .build();
11580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011581 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011582 InputEventInjectionSync::WAIT_FOR_RESULT))
11583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011584 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011585 spyRight->consumeMotionDown();
11586}
11587
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011588/**
11589 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11590 * windows should be allowed to control split touch.
11591 */
11592TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011593 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011594 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011595 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011596 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011597
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011598 auto window = createForeground();
11599 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011600
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011601 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011602
11603 // First finger down, no window touched.
11604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011605 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011606 {100, 200}))
11607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11608 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11609 window->assertNoEvents();
11610
11611 // Second finger down on window, the window should receive touch down.
11612 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011613 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011614 .displayId(ADISPLAY_ID_DEFAULT)
11615 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011616 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11617 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011618 .build();
11619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011620 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011621 InputEventInjectionSync::WAIT_FOR_RESULT))
11622 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11623
11624 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011625 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011626}
11627
11628/**
11629 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11630 * do not receive key events.
11631 */
11632TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011633 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011634 spy->setFocusable(false);
11635
11636 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011637 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011638 setFocusedWindow(window);
11639 window->consumeFocusEvent(true);
11640
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11643 window->consumeKeyDown(ADISPLAY_ID_NONE);
11644
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011646 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11647 window->consumeKeyUp(ADISPLAY_ID_NONE);
11648
11649 spy->assertNoEvents();
11650}
11651
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011652using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11653
11654/**
11655 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11656 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11657 */
11658TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11659 auto window = createForeground();
11660 auto spy1 = createSpy();
11661 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011662 mDispatcher->onWindowInfosChanged(
11663 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011664
11665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011666 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11668 window->consumeMotionDown();
11669 spy1->consumeMotionDown();
11670 spy2->consumeMotionDown();
11671
11672 // Pilfer pointers from the second spy window.
11673 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11674 spy2->assertNoEvents();
11675 spy1->consumeMotionCancel();
11676 window->consumeMotionCancel();
11677
11678 // The rest of the gesture should only be sent to the second spy window.
11679 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011680 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011681 ADISPLAY_ID_DEFAULT))
11682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11683 spy2->consumeMotionMove();
11684 spy1->assertNoEvents();
11685 window->assertNoEvents();
11686}
11687
11688/**
11689 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11690 * in the middle of the gesture.
11691 */
11692TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11693 auto window = createForeground();
11694 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011695 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011696
11697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011698 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11700 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11701 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11702
11703 window->releaseChannel();
11704
11705 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11706
11707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011708 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11710 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11711}
11712
11713/**
11714 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11715 * the spy, but not to any other windows.
11716 */
11717TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11718 auto spy = createSpy();
11719 auto window = createForeground();
11720
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011721 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011722
11723 // First finger down on the window and the spy.
11724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011726 {100, 200}))
11727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11728 spy->consumeMotionDown();
11729 window->consumeMotionDown();
11730
11731 // Spy window pilfers the pointers.
11732 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11733 window->consumeMotionCancel();
11734
11735 // Second finger down on the window and spy, but the window should not receive the pointer down.
11736 const MotionEvent secondFingerDownEvent =
11737 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11738 .displayId(ADISPLAY_ID_DEFAULT)
11739 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011740 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11741 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011742 .build();
11743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011744 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011745 InputEventInjectionSync::WAIT_FOR_RESULT))
11746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11747
Harry Cutts33476232023-01-30 19:57:29 +000011748 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011749
11750 // Third finger goes down outside all windows, so injection should fail.
11751 const MotionEvent thirdFingerDownEvent =
11752 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11753 .displayId(ADISPLAY_ID_DEFAULT)
11754 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011755 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11756 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11757 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011758 .build();
11759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011760 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011761 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011762 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011763
11764 spy->assertNoEvents();
11765 window->assertNoEvents();
11766}
11767
11768/**
11769 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11770 */
11771TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11772 auto spy = createSpy();
11773 spy->setFrame(Rect(0, 0, 100, 100));
11774 auto window = createForeground();
11775 window->setFrame(Rect(0, 0, 200, 200));
11776
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011777 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011778
11779 // First finger down on the window only
11780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011781 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011782 {150, 150}))
11783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11784 window->consumeMotionDown();
11785
11786 // Second finger down on the spy and window
11787 const MotionEvent secondFingerDownEvent =
11788 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11789 .displayId(ADISPLAY_ID_DEFAULT)
11790 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011791 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11792 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011793 .build();
11794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011795 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011796 InputEventInjectionSync::WAIT_FOR_RESULT))
11797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11798 spy->consumeMotionDown();
11799 window->consumeMotionPointerDown(1);
11800
11801 // Third finger down on the spy and window
11802 const MotionEvent thirdFingerDownEvent =
11803 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11804 .displayId(ADISPLAY_ID_DEFAULT)
11805 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011806 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11807 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11808 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011809 .build();
11810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011811 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011812 InputEventInjectionSync::WAIT_FOR_RESULT))
11813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11814 spy->consumeMotionPointerDown(1);
11815 window->consumeMotionPointerDown(2);
11816
11817 // Spy window pilfers the pointers.
11818 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011819 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11820 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011821
11822 spy->assertNoEvents();
11823 window->assertNoEvents();
11824}
11825
11826/**
11827 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11828 * other windows should be canceled. If this results in the cancellation of all pointers for some
11829 * window, then that window should receive ACTION_CANCEL.
11830 */
11831TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11832 auto spy = createSpy();
11833 spy->setFrame(Rect(0, 0, 100, 100));
11834 auto window = createForeground();
11835 window->setFrame(Rect(0, 0, 200, 200));
11836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011837 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011838
11839 // First finger down on both spy and window
11840 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011841 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011842 {10, 10}))
11843 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11844 window->consumeMotionDown();
11845 spy->consumeMotionDown();
11846
11847 // Second finger down on the spy and window
11848 const MotionEvent secondFingerDownEvent =
11849 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11850 .displayId(ADISPLAY_ID_DEFAULT)
11851 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011852 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11853 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011854 .build();
11855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011856 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011857 InputEventInjectionSync::WAIT_FOR_RESULT))
11858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11859 spy->consumeMotionPointerDown(1);
11860 window->consumeMotionPointerDown(1);
11861
11862 // Spy window pilfers the pointers.
11863 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11864 window->consumeMotionCancel();
11865
11866 spy->assertNoEvents();
11867 window->assertNoEvents();
11868}
11869
11870/**
11871 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11872 * be sent to other windows
11873 */
11874TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11875 auto spy = createSpy();
11876 spy->setFrame(Rect(0, 0, 100, 100));
11877 auto window = createForeground();
11878 window->setFrame(Rect(0, 0, 200, 200));
11879
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011880 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011881
11882 // First finger down on both window and spy
11883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011885 {10, 10}))
11886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11887 window->consumeMotionDown();
11888 spy->consumeMotionDown();
11889
11890 // Spy window pilfers the pointers.
11891 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11892 window->consumeMotionCancel();
11893
11894 // Second finger down on the window only
11895 const MotionEvent secondFingerDownEvent =
11896 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11897 .displayId(ADISPLAY_ID_DEFAULT)
11898 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011899 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11900 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011901 .build();
11902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011903 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011904 InputEventInjectionSync::WAIT_FOR_RESULT))
11905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11906 window->consumeMotionDown();
11907 window->assertNoEvents();
11908
11909 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11910 spy->consumeMotionMove();
11911 spy->assertNoEvents();
11912}
11913
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011914/**
11915 * A window on the left and a window on the right. Also, a spy window that's above all of the
11916 * windows, and spanning both left and right windows.
11917 * Send simultaneous motion streams from two different devices, one to the left window, and another
11918 * to the right window.
11919 * Pilfer from spy window.
11920 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11921 */
11922TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11923 sp<FakeWindowHandle> spy = createSpy();
11924 spy->setFrame(Rect(0, 0, 200, 200));
11925 sp<FakeWindowHandle> leftWindow = createForeground();
11926 leftWindow->setFrame(Rect(0, 0, 100, 100));
11927
11928 sp<FakeWindowHandle> rightWindow = createForeground();
11929 rightWindow->setFrame(Rect(100, 0, 200, 100));
11930
11931 constexpr int32_t stylusDeviceId = 1;
11932 constexpr int32_t touchDeviceId = 2;
11933
11934 mDispatcher->onWindowInfosChanged(
11935 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11936
11937 // Stylus down on left window and spy
11938 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11939 .deviceId(stylusDeviceId)
11940 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11941 .build());
11942 leftWindow->consumeMotionEvent(
11943 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11944 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11945
11946 // Finger down on right window and spy - but spy already has stylus
11947 mDispatcher->notifyMotion(
11948 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11949 .deviceId(touchDeviceId)
11950 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11951 .build());
11952 rightWindow->consumeMotionEvent(
11953 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011954 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011955
11956 // Act: pilfer from spy. Spy is currently receiving touch events.
11957 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011958 leftWindow->consumeMotionEvent(
11959 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011960 rightWindow->consumeMotionEvent(
11961 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11962
11963 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11964 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11965 .deviceId(stylusDeviceId)
11966 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11967 .build());
11968 mDispatcher->notifyMotion(
11969 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11970 .deviceId(touchDeviceId)
11971 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11972 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011973 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011974
11975 spy->assertNoEvents();
11976 leftWindow->assertNoEvents();
11977 rightWindow->assertNoEvents();
11978}
11979
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011980TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11981 auto window = createForeground();
11982 auto spy = createSpy();
11983 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11984
11985 mDispatcher->notifyMotion(
11986 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11987 .deviceId(1)
11988 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11989 .build());
11990 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11991 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11992
11993 // Pilfer pointers from the spy window should fail.
11994 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11995 spy->assertNoEvents();
11996 window->assertNoEvents();
11997}
11998
Prabir Pradhand65552b2021-10-07 11:23:50 -070011999class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
12000public:
12001 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
12002 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12003 std::make_shared<FakeApplicationHandle>();
12004 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012005 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12006 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012007 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012008 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012009 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012010 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012011 overlay->setTrustedOverlay(true);
12012
12013 std::shared_ptr<FakeApplicationHandle> application =
12014 std::make_shared<FakeApplicationHandle>();
12015 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012016 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
12017 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012018 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012019 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012020
12021 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012022 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012023 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012024 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012025 return {std::move(overlay), std::move(window)};
12026 }
12027
12028 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012029 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012030 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012031 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012032 }
12033
12034 void sendStylusEvent(int32_t action) {
12035 NotifyMotionArgs motionArgs =
12036 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12037 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012038 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012039 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012040 }
12041};
12042
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012043using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12044
12045TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012046 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012047 ScopedSilentDeath _silentDeath;
12048
Prabir Pradhand65552b2021-10-07 11:23:50 -070012049 auto [overlay, window] = setupStylusOverlayScenario();
12050 overlay->setTrustedOverlay(false);
12051 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012052 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12053 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012054 ".* not a trusted overlay");
12055}
12056
12057TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12058 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012059 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012060
12061 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12062 overlay->consumeMotionDown();
12063 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12064 overlay->consumeMotionUp();
12065
12066 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12067 window->consumeMotionDown();
12068 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12069 window->consumeMotionUp();
12070
12071 overlay->assertNoEvents();
12072 window->assertNoEvents();
12073}
12074
12075TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12076 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012077 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012078 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012079
12080 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12081 overlay->consumeMotionDown();
12082 window->consumeMotionDown();
12083 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12084 overlay->consumeMotionUp();
12085 window->consumeMotionUp();
12086
12087 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12088 window->consumeMotionDown();
12089 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12090 window->consumeMotionUp();
12091
12092 overlay->assertNoEvents();
12093 window->assertNoEvents();
12094}
12095
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012096/**
12097 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12098 * The scenario is as follows:
12099 * - The stylus interceptor overlay is configured as a spy window.
12100 * - The stylus interceptor spy receives the start of a new stylus gesture.
12101 * - It pilfers pointers and then configures itself to no longer be a spy.
12102 * - The stylus interceptor continues to receive the rest of the gesture.
12103 */
12104TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12105 auto [overlay, window] = setupStylusOverlayScenario();
12106 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012107 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012108
12109 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12110 overlay->consumeMotionDown();
12111 window->consumeMotionDown();
12112
12113 // The interceptor pilfers the pointers.
12114 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12115 window->consumeMotionCancel();
12116
12117 // The interceptor configures itself so that it is no longer a spy.
12118 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012119 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012120
12121 // It continues to receive the rest of the stylus gesture.
12122 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12123 overlay->consumeMotionMove();
12124 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12125 overlay->consumeMotionUp();
12126
12127 window->assertNoEvents();
12128}
12129
Prabir Pradhan5735a322022-04-11 17:23:34 +000012130struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012131 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012132 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012133 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12134 std::unique_ptr<InputDispatcher>& mDispatcher;
12135
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012136 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012137 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12138
12139 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012140 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012141 ADISPLAY_ID_DEFAULT, {100, 200},
12142 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12143 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12144 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12145 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12146 }
12147
12148 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012149 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012150 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012151 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012152 mPolicyFlags);
12153 }
12154
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012155 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012156 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12157 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012158 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12159 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012160 window->setOwnerInfo(mPid, mUid);
12161 return window;
12162 }
12163};
12164
12165using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12166
12167TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012168 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012169 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012171
12172 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12173 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12174 window->consumeMotionDown();
12175
12176 setFocusedWindow(window);
12177 window->consumeFocusEvent(true);
12178
12179 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12180 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12181 window->consumeKeyDown(ADISPLAY_ID_NONE);
12182}
12183
12184TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012185 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012186 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012187 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012188
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012189 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012190 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12191 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12192
12193 setFocusedWindow(window);
12194 window->consumeFocusEvent(true);
12195
12196 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12197 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12198 window->assertNoEvents();
12199}
12200
12201TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012202 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012203 auto window = owner.createWindow("Owned window");
12204 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012205 spy->setSpy(true);
12206 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012207 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012208
12209 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12210 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12211 spy->consumeMotionDown();
12212 window->consumeMotionDown();
12213}
12214
12215TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012216 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012217 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012218
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012219 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012220 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012221 randosSpy->setSpy(true);
12222 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012223 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012224
12225 // The event is targeted at owner's window, so injection should succeed, but the spy should
12226 // not receive the event.
12227 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12228 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12229 randosSpy->assertNoEvents();
12230 window->consumeMotionDown();
12231}
12232
12233TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012234 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012235 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012236
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012237 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012238 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012239 randosSpy->setSpy(true);
12240 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012241 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012242
12243 // A user that has injection permission can inject into any window.
12244 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012245 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012246 ADISPLAY_ID_DEFAULT));
12247 randosSpy->consumeMotionDown();
12248 window->consumeMotionDown();
12249
12250 setFocusedWindow(randosSpy);
12251 randosSpy->consumeFocusEvent(true);
12252
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012253 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012254 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12255 window->assertNoEvents();
12256}
12257
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012258TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012259 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012260 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012261
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012262 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012263 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012264 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12265 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012266 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012267
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012268 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012269 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12270 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12271 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012272 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012273}
12274
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012275using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12276
12277TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12279
12280 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12281 ADISPLAY_ID_DEFAULT);
12282 left->setFrame(Rect(0, 0, 100, 100));
12283 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12284 "Right Window", ADISPLAY_ID_DEFAULT);
12285 right->setFrame(Rect(100, 0, 200, 100));
12286 sp<FakeWindowHandle> spy =
12287 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12288 spy->setFrame(Rect(0, 0, 200, 100));
12289 spy->setTrustedOverlay(true);
12290 spy->setSpy(true);
12291
12292 mDispatcher->onWindowInfosChanged(
12293 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12294
12295 // Hover into the left window.
12296 mDispatcher->notifyMotion(
12297 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12298 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12299 .build());
12300
12301 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12302 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12303
12304 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12305 /*pointerId=*/0));
12306 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12307 /*pointerId=*/0));
12308 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12309 /*pointerId=*/0));
12310
12311 // Hover move to the right window.
12312 mDispatcher->notifyMotion(
12313 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12314 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12315 .build());
12316
12317 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12318 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12319 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12320
12321 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12322 /*pointerId=*/0));
12323 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12324 /*pointerId=*/0));
12325 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12326 /*pointerId=*/0));
12327
12328 // Stop hovering.
12329 mDispatcher->notifyMotion(
12330 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12331 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12332 .build());
12333
12334 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12335 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12336
12337 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12338 /*pointerId=*/0));
12339 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12340 /*pointerId=*/0));
12341 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12342 /*pointerId=*/0));
12343}
12344
12345TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12346 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12347
12348 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12349 ADISPLAY_ID_DEFAULT);
12350 left->setFrame(Rect(0, 0, 100, 100));
12351 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12352 "Right Window", ADISPLAY_ID_DEFAULT);
12353 right->setFrame(Rect(100, 0, 200, 100));
12354 sp<FakeWindowHandle> spy =
12355 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12356 spy->setFrame(Rect(0, 0, 200, 100));
12357 spy->setTrustedOverlay(true);
12358 spy->setSpy(true);
12359
12360 mDispatcher->onWindowInfosChanged(
12361 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12362
12363 // First pointer down on left window.
12364 mDispatcher->notifyMotion(
12365 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12366 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12367 .build());
12368
12369 left->consumeMotionDown();
12370 spy->consumeMotionDown();
12371
12372 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12373 /*pointerId=*/0));
12374 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12375 /*pointerId=*/0));
12376 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12377 /*pointerId=*/0));
12378
12379 // Second pointer down on right window.
12380 mDispatcher->notifyMotion(
12381 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12382 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12383 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12384 .build());
12385
12386 left->consumeMotionMove();
12387 right->consumeMotionDown();
12388 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12389
12390 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12391 /*pointerId=*/0));
12392 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12393 /*pointerId=*/0));
12394 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12395 /*pointerId=*/0));
12396 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12397 /*pointerId=*/1));
12398 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12399 /*pointerId=*/1));
12400 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12401 /*pointerId=*/1));
12402
12403 // Second pointer up.
12404 mDispatcher->notifyMotion(
12405 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12406 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12407 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12408 .build());
12409
12410 left->consumeMotionMove();
12411 right->consumeMotionUp();
12412 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12413
12414 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12415 /*pointerId=*/0));
12416 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12417 /*pointerId=*/0));
12418 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12419 /*pointerId=*/0));
12420 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12421 /*pointerId=*/1));
12422 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12423 /*pointerId=*/1));
12424 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12425 /*pointerId=*/1));
12426
12427 // First pointer up.
12428 mDispatcher->notifyMotion(
12429 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12430 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12431 .build());
12432
12433 left->consumeMotionUp();
12434 spy->consumeMotionUp();
12435
12436 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12437 /*pointerId=*/0));
12438 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12439 /*pointerId=*/0));
12440 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12441 /*pointerId=*/0));
12442}
12443
12444TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12446
12447 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12448 ADISPLAY_ID_DEFAULT);
12449 left->setFrame(Rect(0, 0, 100, 100));
12450 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12451 "Right Window", ADISPLAY_ID_DEFAULT);
12452 right->setFrame(Rect(100, 0, 200, 100));
12453
12454 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12455
12456 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12457 /*pointerId=*/0));
12458 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12459 /*pointerId=*/0));
12460
12461 // Hover move into the window.
12462 mDispatcher->notifyMotion(
12463 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12464 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12465 .rawXCursorPosition(50)
12466 .rawYCursorPosition(50)
12467 .deviceId(DEVICE_ID)
12468 .build());
12469
12470 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12471
12472 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12473 /*pointerId=*/0));
12474
12475 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12476 mDispatcher->notifyMotion(
12477 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12478 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12479 .rawXCursorPosition(51)
12480 .rawYCursorPosition(50)
12481 .deviceId(SECOND_DEVICE_ID)
12482 .build());
12483
12484 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12485 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12486
12487 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12488 // a HOVER_EXIT from the first device.
12489 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12490 /*pointerId=*/0));
12491 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12492 SECOND_DEVICE_ID,
12493 /*pointerId=*/0));
12494
12495 // Move the mouse outside the window. Document the current behavior, where the window does not
12496 // receive HOVER_EXIT even though the mouse left the window.
12497 mDispatcher->notifyMotion(
12498 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12499 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12500 .rawXCursorPosition(150)
12501 .rawYCursorPosition(50)
12502 .deviceId(SECOND_DEVICE_ID)
12503 .build());
12504
12505 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12506 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12507 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12508 /*pointerId=*/0));
12509 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12510 SECOND_DEVICE_ID,
12511 /*pointerId=*/0));
12512}
12513
Garfield Tane84e6f92019-08-29 17:28:41 -070012514} // namespace android::inputdispatcher