blob: 9e3a4f10efe0341248336e0415b69cb3ff30c385 [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
Linnan Li5e5645e2024-03-05 14:43:05 +00005372// This test verifies the occlusion detection for all rotations of the display by tapping
5373// in different locations on the display, specifically points close to the four corners of a
5374// window.
5375TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
5376 constexpr static int32_t displayWidth = 400;
5377 constexpr static int32_t displayHeight = 800;
5378
5379 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
5380 std::make_shared<FakeApplicationHandle>();
5381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5382
5383 const auto rotation = GetParam();
5384
5385 // Set up the display with the specified rotation.
5386 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5387 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5388 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5389 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5390 logicalDisplayWidth, logicalDisplayHeight);
5391 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5392
5393 // Create a window that not trusted.
5394 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
5395
5396 const Rect untrustedWindowFrameInDisplay =
5397 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
5398
5399 sp<FakeWindowHandle> untrustedWindow =
5400 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
5401 ADISPLAY_ID_DEFAULT);
5402 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
5403 untrustedWindow->setTrustedOverlay(false);
5404 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
5405 untrustedWindow->setTouchable(false);
5406 untrustedWindow->setAlpha(1.0f);
5407 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5408 addWindow(untrustedWindow);
5409
5410 // Create a simple app window below the untrusted window.
5411 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
5412 const Rect simpleAppWindowFrameInDisplay =
5413 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
5414
5415 sp<FakeWindowHandle> simpleAppWindow =
5416 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
5417 ADISPLAY_ID_DEFAULT);
5418 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
5419 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5420 addWindow(simpleAppWindow);
5421
5422 // The following points in logical display space should be inside the untrusted window, so
5423 // the simple window could not receive events that coordinate is these point.
5424 static const std::array<vec2, 4> untrustedPoints{
5425 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5426
5427 for (const auto untrustedPoint : untrustedPoints) {
5428 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
5429 const PointF pointInDisplaySpace{p.x, p.y};
5430 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5431 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5432 {pointInDisplaySpace}));
5433 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5434 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5435 {pointInDisplaySpace}));
5436 }
5437 untrustedWindow->assertNoEvents();
5438 simpleAppWindow->assertNoEvents();
5439 // The following points in logical display space should be outside the untrusted window, so
5440 // the simple window should receive events that coordinate is these point.
5441 static const std::array<vec2, 5> trustedPoints{
5442 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5443 for (const auto trustedPoint : trustedPoints) {
5444 const vec2 p = displayTransform.inverse().transform(trustedPoint);
5445 const PointF pointInDisplaySpace{p.x, p.y};
5446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5447 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5448 {pointInDisplaySpace}));
5449 simpleAppWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5450 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5453 {pointInDisplaySpace}));
5454 simpleAppWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5455 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
5456 }
5457 untrustedWindow->assertNoEvents();
5458}
5459
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005460// Run the precision tests for all rotations.
5461INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5462 InputDispatcherDisplayOrientationFixture,
5463 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5464 ui::ROTATION_270),
5465 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5466 return ftl::enum_string(testParamInfo.param);
5467 });
5468
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005469using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5470 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005471
5472class TransferTouchFixture : public InputDispatcherTest,
5473 public ::testing::WithParamInterface<TransferFunction> {};
5474
5475TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005477
5478 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005479 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005480 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5481 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005482 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005483 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005484 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5485 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005486 sp<FakeWindowHandle> wallpaper =
5487 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5488 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005489 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005490 mDispatcher->onWindowInfosChanged(
5491 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005492 setFocusedWindow(firstWindow);
5493 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005494
5495 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005496 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5497 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005498
Svet Ganov5d3bc372020-01-26 23:11:07 -08005499 // Only the first window should get the down event
5500 firstWindow->consumeMotionDown();
5501 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005502 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005503 // Dispatcher reports pointer down outside focus for the wallpaper
5504 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005505
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005506 // Transfer touch to the second window
5507 TransferFunction f = GetParam();
5508 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5509 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005510 // The first window gets cancel and the second gets down
5511 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005512 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005513 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005514 // There should not be any changes to the focused window when transferring touch
5515 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005516
5517 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005518 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5519 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005520 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005521 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005522 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005523 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005524}
5525
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005526/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005527 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5528 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5529 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005530 * natural to the user.
5531 * In this test, we are sending a pointer to both spy window and first window. We then try to
5532 * transfer touch to the second window. The dispatcher should identify the first window as the
5533 * one that should lose the gesture, and therefore the action should be to move the gesture from
5534 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005535 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5536 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005537 */
5538TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5540
5541 // Create a couple of windows + a spy window
5542 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005543 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005544 spyWindow->setTrustedOverlay(true);
5545 spyWindow->setSpy(true);
5546 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005547 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005548 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005549 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005550
5551 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005552 mDispatcher->onWindowInfosChanged(
5553 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005554
5555 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005556 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5557 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005558 // Only the first window and spy should get the down event
5559 spyWindow->consumeMotionDown();
5560 firstWindow->consumeMotionDown();
5561
5562 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005563 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005564 TransferFunction f = GetParam();
5565 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5566 ASSERT_TRUE(success);
5567 // The first window gets cancel and the second gets down
5568 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005569 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005570
5571 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5573 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005574 // The first window gets no events and the second+spy get up
5575 firstWindow->assertNoEvents();
5576 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005577 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005578}
5579
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005580TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005581 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005582
5583 PointF touchPoint = {10, 10};
5584
5585 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005586 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005587 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5588 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005589 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005590 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005591 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5592 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005593 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005594
5595 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005596 mDispatcher->onWindowInfosChanged(
5597 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005598
5599 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005600 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5601 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5602 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005603 // Only the first window should get the down event
5604 firstWindow->consumeMotionDown();
5605 secondWindow->assertNoEvents();
5606
5607 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005608 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5609 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005610 // Only the first window should get the pointer down event
5611 firstWindow->consumeMotionPointerDown(1);
5612 secondWindow->assertNoEvents();
5613
5614 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005615 TransferFunction f = GetParam();
5616 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5617 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005618 // The first window gets cancel and the second gets down and pointer down
5619 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005620 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5621 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5622 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005623
5624 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005625 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5626 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005627 // The first window gets nothing and the second gets pointer up
5628 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005629 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5630 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005631
5632 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005633 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5634 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005635 // The first window gets nothing and the second gets up
5636 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005637 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005638}
5639
Arthur Hungc539dbb2022-12-08 07:45:36 +00005640TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5641 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5642
5643 // Create a couple of windows
5644 sp<FakeWindowHandle> firstWindow =
5645 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5646 ADISPLAY_ID_DEFAULT);
5647 firstWindow->setDupTouchToWallpaper(true);
5648 sp<FakeWindowHandle> secondWindow =
5649 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5650 ADISPLAY_ID_DEFAULT);
5651 secondWindow->setDupTouchToWallpaper(true);
5652
5653 sp<FakeWindowHandle> wallpaper1 =
5654 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5655 wallpaper1->setIsWallpaper(true);
5656
5657 sp<FakeWindowHandle> wallpaper2 =
5658 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5659 wallpaper2->setIsWallpaper(true);
5660 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005661 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5662 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5663 {},
5664 0,
5665 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005666
5667 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005668 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5669 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005670
5671 // Only the first window should get the down event
5672 firstWindow->consumeMotionDown();
5673 secondWindow->assertNoEvents();
5674 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5675 wallpaper2->assertNoEvents();
5676
5677 // Transfer touch focus to the second window
5678 TransferFunction f = GetParam();
5679 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5680 ASSERT_TRUE(success);
5681
5682 // The first window gets cancel and the second gets down
5683 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005684 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005685 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005686 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5687 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005688
5689 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005690 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5691 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005692 // The first window gets no events and the second gets up
5693 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005694 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005695 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005696 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5697 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005698}
5699
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005700// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005701// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005702// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005703INSTANTIATE_TEST_SUITE_P(
5704 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5705 ::testing::Values(
5706 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5707 sp<IBinder> destChannelToken) {
5708 return dispatcher->transferTouchOnDisplay(destChannelToken,
5709 ADISPLAY_ID_DEFAULT);
5710 },
5711 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5712 sp<IBinder> to) {
5713 return dispatcher->transferTouchGesture(from, to,
5714 /*isDragAndDrop=*/false);
5715 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005716
Prabir Pradhan367f3432024-02-13 23:05:58 +00005717TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005719
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005720 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005721 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5722 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005723 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005724
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005725 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005726 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5727 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005728 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005729
5730 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005731 mDispatcher->onWindowInfosChanged(
5732 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005733
5734 PointF pointInFirst = {300, 200};
5735 PointF pointInSecond = {300, 600};
5736
5737 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005738 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5739 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5740 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005741 // Only the first window should get the down event
5742 firstWindow->consumeMotionDown();
5743 secondWindow->assertNoEvents();
5744
5745 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005746 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5747 ADISPLAY_ID_DEFAULT,
5748 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005749 // The first window gets a move and the second a down
5750 firstWindow->consumeMotionMove();
5751 secondWindow->consumeMotionDown();
5752
Prabir Pradhan367f3432024-02-13 23:05:58 +00005753 // Transfer touch to the second window
5754 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005755 // The first window gets cancel and the new gets pointer down (it already saw down)
5756 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005757 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5758 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005759
5760 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005761 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5762 ADISPLAY_ID_DEFAULT,
5763 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005764 // The first window gets nothing and the second gets pointer up
5765 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005766 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5767 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005768
5769 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005770 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5771 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005772 // The first window gets nothing and the second gets up
5773 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005774 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005775}
5776
Prabir Pradhan367f3432024-02-13 23:05:58 +00005777// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5778// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5779// receiving touch is not supported, so the touch should continue on those windows and the
5780// transferred-to window should get nothing.
5781TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005782 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5783
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005784 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005785 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5786 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005787 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005788
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005789 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005790 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5791 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005792 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005793
5794 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005795 mDispatcher->onWindowInfosChanged(
5796 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005797
5798 PointF pointInFirst = {300, 200};
5799 PointF pointInSecond = {300, 600};
5800
5801 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005802 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5803 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5804 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005805 // Only the first window should get the down event
5806 firstWindow->consumeMotionDown();
5807 secondWindow->assertNoEvents();
5808
5809 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005810 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5811 ADISPLAY_ID_DEFAULT,
5812 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005813 // The first window gets a move and the second a down
5814 firstWindow->consumeMotionMove();
5815 secondWindow->consumeMotionDown();
5816
5817 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005818 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005819 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5820 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005821 ASSERT_FALSE(transferred);
5822 firstWindow->assertNoEvents();
5823 secondWindow->assertNoEvents();
5824
5825 // The rest of the dispatch should proceed as normal
5826 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005827 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5828 ADISPLAY_ID_DEFAULT,
5829 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005830 // The first window gets MOVE and the second gets pointer up
5831 firstWindow->consumeMotionMove();
5832 secondWindow->consumeMotionUp();
5833
5834 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005835 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5836 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005837 // The first window gets nothing and the second gets up
5838 firstWindow->consumeMotionUp();
5839 secondWindow->assertNoEvents();
5840}
5841
Arthur Hungabbb9d82021-09-01 14:52:30 +00005842// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005843// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005844// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005845TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005846 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5847 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005848 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005849 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005850 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005851 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005852 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005853
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005854 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005855 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005856
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005857 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005858 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005859
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005860 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005861 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005862
5863 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005864 mDispatcher->onWindowInfosChanged(
5865 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5866 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5867 *secondWindowInPrimary->getInfo()},
5868 {},
5869 0,
5870 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005871
5872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005873 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005874 {50, 50}))
5875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5876
5877 // Window should receive motion event.
5878 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5879
Prabir Pradhan367f3432024-02-13 23:05:58 +00005880 // Transfer touch
5881 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5882 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005883 // The first window gets cancel.
5884 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005885 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5886 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005887
5888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005889 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005890 ADISPLAY_ID_DEFAULT, {150, 50}))
5891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5892 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005893 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5894 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005895
5896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005897 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005898 {150, 50}))
5899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5900 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005901 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005902}
5903
Prabir Pradhan367f3432024-02-13 23:05:58 +00005904// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5905// 'transferTouchOnDisplay' api.
5906TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5908 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005909 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005910 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005911 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005912 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005913 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005914
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005915 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005916 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005917
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005918 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005919 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005920
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005921 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005922 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005923
5924 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005925 mDispatcher->onWindowInfosChanged(
5926 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5927 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5928 *secondWindowInPrimary->getInfo()},
5929 {},
5930 0,
5931 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005932
5933 // Touch on second display.
5934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005935 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5936 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005937 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5938
5939 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005940 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005941
5942 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005943 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5944 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005945
5946 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005947 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005948 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5949 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005950
5951 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005952 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005953 SECOND_DISPLAY_ID, {150, 50}))
5954 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005955 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005956 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5957 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005958
5959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005960 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005962 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005963 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005964}
5965
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005966TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005968 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5969 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005970
Vishnu Nair47074b82020-08-14 11:54:47 -07005971 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005972 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005973 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005974
5975 window->consumeFocusEvent(true);
5976
Prabir Pradhan678438e2023-04-13 19:32:51 +00005977 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005978
5979 // Window should receive key down event.
5980 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005981
5982 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005983 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005984 mFakePolicy->assertUserActivityPoked();
5985}
5986
5987TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5989 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5990 "Fake Window", ADISPLAY_ID_DEFAULT);
5991
5992 window->setDisableUserActivity(true);
5993 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005994 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005995 setFocusedWindow(window);
5996
5997 window->consumeFocusEvent(true);
5998
5999 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6000
6001 // Window should receive key down event.
6002 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6003
6004 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006005 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006006 mFakePolicy->assertUserActivityNotPoked();
6007}
6008
6009TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
6010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6011 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6012 "Fake Window", ADISPLAY_ID_DEFAULT);
6013
6014 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006016 setFocusedWindow(window);
6017
6018 window->consumeFocusEvent(true);
6019
6020 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6021 mDispatcher->waitForIdle();
6022
6023 // System key is not passed down
6024 window->assertNoEvents();
6025
6026 // Should have poked user activity
6027 mFakePolicy->assertUserActivityPoked();
6028}
6029
6030TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
6031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6032 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6033 "Fake Window", ADISPLAY_ID_DEFAULT);
6034
6035 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006036 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006037 setFocusedWindow(window);
6038
6039 window->consumeFocusEvent(true);
6040
6041 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6042 mDispatcher->waitForIdle();
6043
6044 // System key is not passed down
6045 window->assertNoEvents();
6046
6047 // Should have poked user activity
6048 mFakePolicy->assertUserActivityPoked();
6049}
6050
6051TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
6052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6053 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6054 "Fake Window", ADISPLAY_ID_DEFAULT);
6055
6056 window->setDisableUserActivity(true);
6057 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006058 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006059 setFocusedWindow(window);
6060
6061 window->consumeFocusEvent(true);
6062
6063 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
6064 mDispatcher->waitForIdle();
6065
6066 // System key is not passed down
6067 window->assertNoEvents();
6068
6069 // Should have poked user activity
6070 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006071}
6072
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006073TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6075 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6076 "Fake Window", ADISPLAY_ID_DEFAULT);
6077
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006078 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006079
6080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006081 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006082 ADISPLAY_ID_DEFAULT, {100, 100}))
6083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6084
6085 window->consumeMotionEvent(
6086 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
6087
6088 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006089 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006090 mFakePolicy->assertUserActivityPoked();
6091}
6092
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006093TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006094 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006095 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6096 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006098 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006099
Prabir Pradhan678438e2023-04-13 19:32:51 +00006100 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006101 mDispatcher->waitForIdle();
6102
6103 window->assertNoEvents();
6104}
6105
6106// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6107TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006109 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6110 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006111
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006112 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006113
6114 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006115 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006116 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006117 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6118 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006119
6120 // Window should receive only the motion event
6121 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6122 window->assertNoEvents(); // Key event or focus event will not be received
6123}
6124
arthurhungea3f4fc2020-12-21 23:18:53 +08006125TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6127
arthurhungea3f4fc2020-12-21 23:18:53 +08006128 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006129 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6130 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006131 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006132
arthurhungea3f4fc2020-12-21 23:18:53 +08006133 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006134 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6135 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006136 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006137
6138 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006139 mDispatcher->onWindowInfosChanged(
6140 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006141
6142 PointF pointInFirst = {300, 200};
6143 PointF pointInSecond = {300, 600};
6144
6145 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006146 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6147 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6148 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006149 // Only the first window should get the down event
6150 firstWindow->consumeMotionDown();
6151 secondWindow->assertNoEvents();
6152
6153 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006154 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6155 ADISPLAY_ID_DEFAULT,
6156 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006157 // The first window gets a move and the second a down
6158 firstWindow->consumeMotionMove();
6159 secondWindow->consumeMotionDown();
6160
6161 // Send pointer cancel to the second window
6162 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006163 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006164 {pointInFirst, pointInSecond});
6165 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006166 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006167 // The first window gets move and the second gets cancel.
6168 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6169 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6170
6171 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006172 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6173 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006174 // The first window gets up and the second gets nothing.
6175 firstWindow->consumeMotionUp();
6176 secondWindow->assertNoEvents();
6177}
6178
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006179TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6180 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6181
6182 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006183 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006184 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006185 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6186 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6187 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6188
Harry Cutts33476232023-01-30 19:57:29 +00006189 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006190 window->assertNoEvents();
6191 mDispatcher->waitForIdle();
6192}
6193
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006194using InputDispatcherMonitorTest = InputDispatcherTest;
6195
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006196/**
6197 * Two entities that receive touch: A window, and a global monitor.
6198 * The touch goes to the window, and then the window disappears.
6199 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6200 * for the monitor, as well.
6201 * 1. foregroundWindow
6202 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6203 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006204TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6206 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006207 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006208
Prabir Pradhanfb549072023-10-05 19:17:36 +00006209 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006210
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006211 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006213 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006214 {100, 200}))
6215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6216
6217 // Both the foreground window and the global monitor should receive the touch down
6218 window->consumeMotionDown();
6219 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6220
6221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006222 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006223 ADISPLAY_ID_DEFAULT, {110, 200}))
6224 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6225
6226 window->consumeMotionMove();
6227 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6228
6229 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006230 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006231 window->consumeMotionCancel();
6232 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6233
6234 // If more events come in, there will be no more foreground window to send them to. This will
6235 // cause a cancel for the monitor, as well.
6236 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006237 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006238 ADISPLAY_ID_DEFAULT, {120, 200}))
6239 << "Injection should fail because the window was removed";
6240 window->assertNoEvents();
6241 // Global monitor now gets the cancel
6242 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6243}
6244
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006245TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006246 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006247 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6248 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006249 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006250
Prabir Pradhanfb549072023-10-05 19:17:36 +00006251 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006252
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006256 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006257 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006258}
6259
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006260TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006261 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006262
Chris Yea209fde2020-07-22 13:54:51 -07006263 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006264 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6265 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006266 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006267
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006269 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006271 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006272 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006273
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006274 // Pilfer pointers from the monitor.
6275 // This should not do anything and the window should continue to receive events.
6276 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006277
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006279 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006280 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006282
6283 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6284 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006285}
6286
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006287TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006289 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6290 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006292 window->setWindowOffset(20, 40);
6293 window->setWindowTransform(0, 1, -1, 0);
6294
Prabir Pradhanfb549072023-10-05 19:17:36 +00006295 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006296
6297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006298 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6300 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006301 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6302 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006303 // Even though window has transform, gesture monitor must not.
6304 ASSERT_EQ(ui::Transform(), event->getTransform());
6305}
6306
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006307TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006309 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006310
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006311 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006312 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006313 << "Injection should fail if there is a monitor, but no touchable window";
6314 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006315}
6316
Linnan Lid8150952024-01-26 18:07:17 +00006317/**
6318 * Two displays
6319 * The first monitor has a foreground window, a monitor
6320 * The second window has only one monitor.
6321 * We first inject a Down event into the first display, this injection should succeed and both
6322 * the foreground window and monitor should receive a down event, then inject a Down event into
6323 * the second display as well, this injection should fail, at this point, the first display
6324 * window and monitor should not receive a cancel or any other event.
6325 * Continue to inject Move and UP events to the first display, the events should be received
6326 * normally by the foreground window and monitor.
6327 */
6328TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6330 sp<FakeWindowHandle> window =
6331 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6332
6333 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6334 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6335
6336 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6338 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6339 {100, 200}))
6340 << "The down event injected into the first display should succeed";
6341
6342 window->consumeMotionDown();
6343 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006344
6345 ASSERT_EQ(InputEventInjectionResult::FAILED,
6346 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6347 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006348 << "The down event injected into the second display should fail since there's no "
6349 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006350
6351 // Continue to inject event to first display.
6352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6353 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6354 ADISPLAY_ID_DEFAULT, {110, 220}))
6355 << "The move event injected into the first display should succeed";
6356
6357 window->consumeMotionMove();
6358 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006359
6360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6361 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6362 {110, 220}))
6363 << "The up event injected into the first display should succeed";
6364
6365 window->consumeMotionUp();
6366 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006367
6368 window->assertNoEvents();
6369 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006370 secondMonitor.assertNoEvents();
6371}
6372
6373/**
6374 * Two displays
6375 * There is a monitor and foreground window on each display.
6376 * First, we inject down events into each of the two displays, at this point, the foreground windows
6377 * and monitors on both displays should receive down events.
6378 * At this point, the foreground window of the second display goes away, the gone window should
6379 * receive the cancel event, and the other windows and monitors should not receive any events.
6380 * Inject a move event into the second display. At this point, the injection should fail because
6381 * the second display no longer has a foreground window. At this point, the monitor on the second
6382 * display should receive a cancel event, and any windows or monitors on the first display should
6383 * not receive any events, and any subsequent injection of events into the second display should
6384 * also fail.
6385 * Continue to inject events into the first display, and the events should all be injected
6386 * successfully and received normally.
6387 */
6388TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6389 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6390 sp<FakeWindowHandle> window =
6391 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6392 sp<FakeWindowHandle> secondWindow =
6393 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6394 SECOND_DISPLAY_ID);
6395
6396 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6397 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6398
6399 // There is a foreground window on both displays.
6400 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6402 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6403 {100, 200}))
6404 << "The down event injected into the first display should succeed";
6405
6406 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6407 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006408
6409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6410 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6411 {100, 200}))
6412 << "The down event injected into the second display should succeed";
6413
Linnan Lid8150952024-01-26 18:07:17 +00006414 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6415 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6416
6417 // Now second window is gone away.
6418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6419
6420 // The gone window should receive a cancel, and the monitor on the second display should not
6421 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006422 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6423 secondMonitor.assertNoEvents();
6424
6425 ASSERT_EQ(InputEventInjectionResult::FAILED,
6426 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6427 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006428 << "The move event injected into the second display should fail because there's no "
6429 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006430 // Now the monitor on the second display should receive a cancel event.
6431 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006432
6433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6434 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6435 ADISPLAY_ID_DEFAULT, {110, 200}))
6436 << "The move event injected into the first display should succeed";
6437
6438 window->consumeMotionMove();
6439 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006440
6441 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006442 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6443 {110, 220}))
6444 << "The up event injected into the second display should fail because there's no "
6445 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006446
6447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6448 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6449 {110, 220}))
6450 << "The up event injected into the first display should succeed";
6451
6452 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6453 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006454
Linnan Lid8150952024-01-26 18:07:17 +00006455 window->assertNoEvents();
6456 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006457 secondWindow->assertNoEvents();
6458 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006459}
6460
6461/**
6462 * One display with transform
6463 * There is a foreground window and a monitor on the display
6464 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6465 * event and move event, then let the foreground window go away, the foreground window receives
6466 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6467 * by the monitor should be with the same transform as the display
6468 */
6469TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6471 sp<FakeWindowHandle> window =
6472 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6473 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6474
6475 ui::Transform transform;
6476 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6477
6478 gui::DisplayInfo displayInfo;
6479 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6480 displayInfo.transform = transform;
6481
6482 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6483
6484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6485 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6486 {100, 200}))
6487 << "The down event injected should succeed";
6488
6489 window->consumeMotionDown();
6490 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6491 EXPECT_EQ(transform, downMotionEvent->getTransform());
6492 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6493
6494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6495 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6496 ADISPLAY_ID_DEFAULT, {110, 220}))
6497 << "The move event injected should succeed";
6498
6499 window->consumeMotionMove();
6500 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6501 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6502 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6503
6504 // Let foreground window gone
6505 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6506
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006507 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006508 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006509
6510 ASSERT_EQ(InputEventInjectionResult::FAILED,
6511 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6512 ADISPLAY_ID_DEFAULT, {110, 220}))
6513 << "The move event injected should failed";
6514 // Now foreground should not receive any events, but monitor should receive a cancel event
6515 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006516 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6517 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6518 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6519 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6520
6521 // Other event inject to this display should fail.
6522 ASSERT_EQ(InputEventInjectionResult::FAILED,
6523 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6524 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006525 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006526 window->assertNoEvents();
6527 monitor.assertNoEvents();
6528}
6529
chaviw81e2bb92019-12-18 15:03:51 -08006530TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006532 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6533 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006534
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006535 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006536
6537 NotifyMotionArgs motionArgs =
6538 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6539 ADISPLAY_ID_DEFAULT);
6540
Prabir Pradhan678438e2023-04-13 19:32:51 +00006541 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006542 // Window should receive motion down event.
6543 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6544
6545 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006546 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006547 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6548 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6549 motionArgs.pointerCoords[0].getX() - 10);
6550
Prabir Pradhan678438e2023-04-13 19:32:51 +00006551 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006552 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006553}
6554
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006555/**
6556 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6557 * the device default right away. In the test scenario, we check both the default value,
6558 * and the action of enabling / disabling.
6559 */
6560TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006561 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006562 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6563 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006564 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006565
6566 // Set focused application.
6567 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006568 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006569
6570 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006571 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006572 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006573 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006574
6575 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006576 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006577 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006578 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006579
6580 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006581 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006582 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006583 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006584 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006585 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006586 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006587 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006588
6589 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006590 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006591 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006592 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006593
6594 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006595 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006596 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006597 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006598 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006599 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006600 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006601 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006602
6603 window->assertNoEvents();
6604}
6605
Gang Wange9087892020-01-07 12:17:14 -05006606TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006608 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6609 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006610
6611 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006612 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006613
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006614 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006615 setFocusedWindow(window);
6616
Harry Cutts33476232023-01-30 19:57:29 +00006617 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006618
Prabir Pradhan678438e2023-04-13 19:32:51 +00006619 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6620 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006621
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006622 std::unique_ptr<KeyEvent> event = window->consumeKey();
6623 ASSERT_NE(event, nullptr);
6624 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006625 ASSERT_NE(verified, nullptr);
6626 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6627
6628 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6629 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6630 ASSERT_EQ(keyArgs.source, verified->source);
6631 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6632
6633 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6634
6635 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006636 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006637 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006638 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6639 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6640 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6641 ASSERT_EQ(0, verifiedKey.repeatCount);
6642}
6643
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006644TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006646 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6647 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006648
6649 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6650
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006651 ui::Transform transform;
6652 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6653
6654 gui::DisplayInfo displayInfo;
6655 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6656 displayInfo.transform = transform;
6657
Patrick Williamsd828f302023-04-28 17:52:08 -05006658 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006659
Prabir Pradhan678438e2023-04-13 19:32:51 +00006660 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006661 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6662 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006663 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006664
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006665 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6666 ASSERT_NE(nullptr, event);
6667 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006668 ASSERT_NE(verified, nullptr);
6669 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6670
6671 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6672 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6673 EXPECT_EQ(motionArgs.source, verified->source);
6674 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6675
6676 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6677
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006678 const vec2 rawXY =
6679 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6680 motionArgs.pointerCoords[0].getXYValue());
6681 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6682 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006683 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006684 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006685 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006686 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6687 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6688}
6689
chaviw09c8d2d2020-08-24 15:48:26 -07006690/**
6691 * Ensure that separate calls to sign the same data are generating the same key.
6692 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6693 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6694 * tests.
6695 */
6696TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6697 KeyEvent event = getTestKeyEvent();
6698 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6699
6700 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6701 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6702 ASSERT_EQ(hmac1, hmac2);
6703}
6704
6705/**
6706 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6707 */
6708TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6709 KeyEvent event = getTestKeyEvent();
6710 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6711 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6712
6713 verifiedEvent.deviceId += 1;
6714 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6715
6716 verifiedEvent.source += 1;
6717 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6718
6719 verifiedEvent.eventTimeNanos += 1;
6720 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6721
6722 verifiedEvent.displayId += 1;
6723 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6724
6725 verifiedEvent.action += 1;
6726 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6727
6728 verifiedEvent.downTimeNanos += 1;
6729 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6730
6731 verifiedEvent.flags += 1;
6732 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6733
6734 verifiedEvent.keyCode += 1;
6735 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6736
6737 verifiedEvent.scanCode += 1;
6738 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6739
6740 verifiedEvent.metaState += 1;
6741 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6742
6743 verifiedEvent.repeatCount += 1;
6744 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6745}
6746
Vishnu Nair958da932020-08-21 17:12:37 -07006747TEST_F(InputDispatcherTest, SetFocusedWindow) {
6748 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 // Top window is also focusable but is not granted focus.
6756 windowTop->setFocusable(true);
6757 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006758 mDispatcher->onWindowInfosChanged(
6759 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006760 setFocusedWindow(windowSecond);
6761
6762 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006764 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006765
6766 // Focused window should receive event.
6767 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6768 windowTop->assertNoEvents();
6769}
6770
6771TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
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 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6776
6777 window->setFocusable(true);
6778 // Release channel for window is no longer valid.
6779 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006781 setFocusedWindow(window);
6782
6783 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006784 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006785
6786 // window channel is invalid, so it should not receive any input event.
6787 window->assertNoEvents();
6788}
6789
6790TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6791 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6792 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006793 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006794 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006795 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6796
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006797 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006798 setFocusedWindow(window);
6799
6800 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006801 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006802
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006803 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006804 window->assertNoEvents();
6805}
6806
6807TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6809 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006810 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006811 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006812 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006813 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6814
6815 windowTop->setFocusable(true);
6816 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006817 mDispatcher->onWindowInfosChanged(
6818 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006819 setFocusedWindow(windowTop);
6820 windowTop->consumeFocusEvent(true);
6821
Chavi Weingarten847e8512023-03-29 00:26:09 +00006822 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006823 mDispatcher->onWindowInfosChanged(
6824 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006825 windowSecond->consumeFocusEvent(true);
6826 windowTop->consumeFocusEvent(false);
6827
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006829 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006830
6831 // Focused window should receive event.
6832 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6833}
6834
Chavi Weingarten847e8512023-03-29 00:26:09 +00006835TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006836 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6837 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006838 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006839 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006840 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006841 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6842
6843 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006844 windowSecond->setFocusable(false);
6845 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006846 mDispatcher->onWindowInfosChanged(
6847 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006848 setFocusedWindow(windowTop);
6849 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006850
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006851 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006852 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006853
6854 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006855 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006856 windowSecond->assertNoEvents();
6857}
6858
6859TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6861 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006862 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006863 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006864 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6865 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006866 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6867
6868 window->setFocusable(true);
6869 previousFocusedWindow->setFocusable(true);
6870 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006871 mDispatcher->onWindowInfosChanged(
6872 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006873 setFocusedWindow(previousFocusedWindow);
6874 previousFocusedWindow->consumeFocusEvent(true);
6875
6876 // Requesting focus on invisible window takes focus from currently focused window.
6877 setFocusedWindow(window);
6878 previousFocusedWindow->consumeFocusEvent(false);
6879
6880 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006881 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006882 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6883 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006884
6885 // Window does not get focus event or key down.
6886 window->assertNoEvents();
6887
6888 // Window becomes visible.
6889 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006890 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006891
6892 // Window receives focus event.
6893 window->consumeFocusEvent(true);
6894 // Focused window receives key down.
6895 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6896}
6897
Vishnu Nair599f1412021-06-21 10:39:58 -07006898TEST_F(InputDispatcherTest, DisplayRemoved) {
6899 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6900 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006901 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006902 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6903
6904 // window is granted focus.
6905 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006907 setFocusedWindow(window);
6908 window->consumeFocusEvent(true);
6909
6910 // When a display is removed window loses focus.
6911 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6912 window->consumeFocusEvent(false);
6913}
6914
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006915/**
6916 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6917 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6918 * of the 'slipperyEnterWindow'.
6919 *
6920 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6921 * a way so that the touched location is no longer covered by the top window.
6922 *
6923 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6924 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6925 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6926 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6927 * with ACTION_DOWN).
6928 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6929 * window moved itself away from the touched location and had Flag::SLIPPERY.
6930 *
6931 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6932 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6933 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6934 *
6935 * In this test, we ensure that the event received by the bottom window has
6936 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6937 */
6938TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006939 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006940 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006941
6942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6943 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6944
6945 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006946 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006947 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006948 // Make sure this one overlaps the bottom window
6949 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6950 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6951 // one. Windows with the same owner are not considered to be occluding each other.
6952 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6953
6954 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006955 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006956 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6957
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006958 mDispatcher->onWindowInfosChanged(
6959 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006960
6961 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006962 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6963 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6964 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006965 slipperyExitWindow->consumeMotionDown();
6966 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006967 mDispatcher->onWindowInfosChanged(
6968 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006969
Prabir Pradhan678438e2023-04-13 19:32:51 +00006970 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6971 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6972 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006973
6974 slipperyExitWindow->consumeMotionCancel();
6975
6976 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6977 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6978}
6979
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006980/**
6981 * Two windows, one on the left and another on the right. The left window is slippery. The right
6982 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6983 * touch moves from the left window into the right window, the gesture should continue to go to the
6984 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6985 * reproduces a crash.
6986 */
6987TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6988 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6989
6990 sp<FakeWindowHandle> leftSlipperyWindow =
6991 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6992 leftSlipperyWindow->setSlippery(true);
6993 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6994
6995 sp<FakeWindowHandle> rightDropTouchesWindow =
6996 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6997 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6998 rightDropTouchesWindow->setDropInput(true);
6999
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007000 mDispatcher->onWindowInfosChanged(
7001 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007002
7003 // Start 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 leftSlipperyWindow->consumeMotionDown();
7008
7009 // And move it into the right window
7010 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7011 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7012 .build());
7013
7014 // Since the right window isn't eligible to receive input, touch does not slip.
7015 // The left window continues to receive the gesture.
7016 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7017 rightDropTouchesWindow->assertNoEvents();
7018}
7019
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007020/**
7021 * A single window is on screen first. Touch is injected into that window. Next, a second window
7022 * appears. Since the first window is slippery, touch will move from the first window to the second.
7023 */
7024TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7025 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7026 sp<FakeWindowHandle> originalWindow =
7027 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
7028 originalWindow->setFrame(Rect(0, 0, 200, 200));
7029 originalWindow->setSlippery(true);
7030
7031 sp<FakeWindowHandle> appearingWindow =
7032 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
7033 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7034
7035 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7036
7037 // Touch down on the original window
7038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7039 injectMotionEvent(*mDispatcher,
7040 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7041 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7042 .build()));
7043 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7044
7045 // Now, a new window appears. This could be, for example, a notification shade that appears
7046 // after user starts to drag down on the launcher window.
7047 mDispatcher->onWindowInfosChanged(
7048 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7050 injectMotionEvent(*mDispatcher,
7051 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7052 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7053 .build()));
7054 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7055 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7057 injectMotionEvent(*mDispatcher,
7058 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7059 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7060 .build()));
7061 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7062
7063 originalWindow->assertNoEvents();
7064 appearingWindow->assertNoEvents();
7065}
7066
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007067TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007068 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7070
7071 sp<FakeWindowHandle> leftWindow =
7072 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
7073 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007074 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007075
7076 sp<FakeWindowHandle> rightSpy =
7077 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
7078 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007079 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007080 rightSpy->setSpy(true);
7081 rightSpy->setTrustedOverlay(true);
7082
7083 sp<FakeWindowHandle> rightWindow =
7084 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
7085 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007086 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007087
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007088 mDispatcher->onWindowInfosChanged(
7089 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007090
7091 // Touch in the left window
7092 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7093 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7094 .build());
7095 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7096 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007097 ASSERT_NO_FATAL_FAILURE(
7098 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007099
7100 // Touch another finger over the right windows
7101 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7102 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7103 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7104 .build());
7105 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7106 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7107 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7108 mDispatcher->waitForIdle();
7109 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007110 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7111 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007112
7113 // Release finger over left window. The UP actions are not treated as device interaction.
7114 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7115 // is part of the UP action, we do not treat this as device interaction.
7116 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7117 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7118 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7119 .build());
7120 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7121 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7122 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7123 mDispatcher->waitForIdle();
7124 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7125
7126 // Move remaining finger
7127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7128 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7129 .build());
7130 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7131 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7132 mDispatcher->waitForIdle();
7133 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007134 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007135
7136 // Release all fingers
7137 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7138 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7139 .build());
7140 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7141 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7142 mDispatcher->waitForIdle();
7143 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7144}
7145
7146TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7148
7149 sp<FakeWindowHandle> window =
7150 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7151 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007152 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007153
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007154 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007155 setFocusedWindow(window);
7156 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7157
7158 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7159 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7160 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007161 ASSERT_NO_FATAL_FAILURE(
7162 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007163
7164 // The UP actions are not treated as device interaction.
7165 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7166 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7167 mDispatcher->waitForIdle();
7168 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7169}
7170
Prabir Pradhan5893d362023-11-17 04:30:40 +00007171TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7173
7174 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7175 ADISPLAY_ID_DEFAULT);
7176 left->setFrame(Rect(0, 0, 100, 100));
7177 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7178 "Right Window", ADISPLAY_ID_DEFAULT);
7179 right->setFrame(Rect(100, 0, 200, 100));
7180 sp<FakeWindowHandle> spy =
7181 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7182 spy->setFrame(Rect(0, 0, 200, 100));
7183 spy->setTrustedOverlay(true);
7184 spy->setSpy(true);
7185
7186 mDispatcher->onWindowInfosChanged(
7187 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7188
7189 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7190 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7191 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7192 mDispatcher->notifyMotion(notifyArgs);
7193
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007194 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007195 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7196 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007197 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007198 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7199 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007200 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007201 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7202
7203 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7204 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7205 {PointF{150, 50}});
7206 mDispatcher->notifyMotion(notifyArgs);
7207
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007208 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007209 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7210 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007211 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007212 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7213 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007214 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007215 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7216
7217 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7218}
7219
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007220class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7221protected:
7222 std::shared_ptr<FakeApplicationHandle> mApp;
7223 sp<FakeWindowHandle> mWindow;
7224
7225 virtual void SetUp() override {
7226 InputDispatcherTest::SetUp();
7227
7228 mApp = std::make_shared<FakeApplicationHandle>();
7229
7230 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7231 mWindow->setFrame(Rect(0, 0, 100, 100));
7232
7233 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7234 setFocusedWindow(mWindow);
7235 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7236 }
7237
7238 void setFallback(int32_t keycode) {
7239 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7240 return KeyEventBuilder(event).keyCode(keycode).build();
7241 });
7242 }
7243
7244 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007245 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7246 ASSERT_NE(nullptr, event);
7247 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007248 }
7249};
7250
7251TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7252 mDispatcher->notifyKey(
7253 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7254 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7255 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7256}
7257
7258TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7259 mDispatcher->notifyKey(
7260 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7261 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7263}
7264
7265TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7266 mDispatcher->notifyKey(
7267 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7268
7269 // Do not handle this key event.
7270 consumeKey(/*handled=*/false,
7271 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7272 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7273
7274 // Since the policy did not request any fallback to be generated, ensure there are no events.
7275 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7276}
7277
7278TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
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.
7284 consumeKey(/*handled=*/false,
7285 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7286
7287 // Since the key was not handled, ensure the fallback event was dispatched instead.
7288 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7289 consumeKey(/*handled=*/true,
7290 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7291 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7292
7293 // Release the original key, and ensure the fallback key is also released.
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 consumeKey(/*handled=*/true,
7300 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7301 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7302
7303 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7304 mWindow->assertNoEvents();
7305}
7306
7307TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7308 setFallback(AKEYCODE_B);
7309 mDispatcher->notifyKey(
7310 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7311
7312 // Do not handle this key event, but handle the fallback.
7313 consumeKey(/*handled=*/false,
7314 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7315 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7316 consumeKey(/*handled=*/true,
7317 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7318 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7319
7320 // Release the original key, and ensure the fallback key is also released.
7321 mDispatcher->notifyKey(
7322 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7323 // But this time, the app handles the original key.
7324 consumeKey(/*handled=*/true,
7325 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7326 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7327 // Ensure the fallback key is canceled.
7328 consumeKey(/*handled=*/true,
7329 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7330 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7331
7332 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7333 mWindow->assertNoEvents();
7334}
7335
7336TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7337 setFallback(AKEYCODE_B);
7338 mDispatcher->notifyKey(
7339 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7340
7341 // Do not handle this key event.
7342 consumeKey(/*handled=*/false,
7343 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7344 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7345 // App does not handle the fallback either, so ensure another fallback is not generated.
7346 setFallback(AKEYCODE_C);
7347 consumeKey(/*handled=*/false,
7348 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7349 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7350
7351 // Release the original key, and ensure the fallback key is also released.
7352 setFallback(AKEYCODE_B);
7353 mDispatcher->notifyKey(
7354 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7355 consumeKey(/*handled=*/false,
7356 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7357 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7358 consumeKey(/*handled=*/false,
7359 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7360 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7361
7362 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7363 mWindow->assertNoEvents();
7364}
7365
7366TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7367 setFallback(AKEYCODE_B);
7368 mDispatcher->notifyKey(
7369 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7370
7371 // Do not handle this key event, so fallback is generated.
7372 consumeKey(/*handled=*/false,
7373 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7374 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7375 consumeKey(/*handled=*/true,
7376 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7377 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7378
7379 // Release the original key, but assume the policy is misbehaving and it
7380 // generates an inconsistent fallback to the one from the DOWN event.
7381 setFallback(AKEYCODE_C);
7382 mDispatcher->notifyKey(
7383 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7384 consumeKey(/*handled=*/false,
7385 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7386 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7387 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7388 consumeKey(/*handled=*/true,
7389 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7390 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7391
7392 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7393 mWindow->assertNoEvents();
7394}
7395
7396TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7397 setFallback(AKEYCODE_B);
7398 mDispatcher->notifyKey(
7399 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7400
7401 // Do not handle this key event, so fallback is generated.
7402 consumeKey(/*handled=*/false,
7403 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7404 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7405 consumeKey(/*handled=*/true,
7406 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7407 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7408
7409 // The original key is canceled.
7410 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7411 .keyCode(AKEYCODE_A)
7412 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7413 .build());
7414 consumeKey(/*handled=*/false,
7415 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7416 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7417 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7418 // Ensure the fallback key is also canceled due to the original key being canceled.
7419 consumeKey(/*handled=*/true,
7420 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7421 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7422
7423 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7424 mWindow->assertNoEvents();
7425}
7426
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007427TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007428 setFallback(AKEYCODE_B);
7429 mDispatcher->notifyKey(
7430 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7431
7432 // Do not handle this key event.
7433 consumeKey(/*handled=*/false,
7434 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7435 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7436 consumeKey(/*handled=*/true,
7437 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7438 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7439
7440 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7441 // When the unhandled key is reported to the policy next, remove the input channel.
7442 mDispatcher->removeInputChannel(mWindow->getToken());
7443 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7444 });
7445 // Release the original key, and let the app now handle the previously unhandled key.
7446 // This should result in the previously generated fallback key to be cancelled.
7447 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7448 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7449 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7450 // the policy call, we will now remove the input channel. Once the policy call returns, the
7451 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7452 // not cause any crashes.
7453 mDispatcher->notifyKey(
7454 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7455 consumeKey(/*handled=*/true,
7456 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7457 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7458}
7459
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007460TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7461 setFallback(AKEYCODE_B);
7462 mDispatcher->notifyKey(
7463 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7464
7465 // Do not handle this key event.
7466 consumeKey(/*handled=*/false,
7467 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7468 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7469 consumeKey(/*handled=*/true,
7470 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7471 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7472
7473 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7474 // When the unhandled key is reported to the policy next, remove the window.
7475 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7476 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7477 });
7478 // Release the original key, which the app will not handle. When this unhandled key is reported
7479 // to the policy, the window will be removed.
7480 mDispatcher->notifyKey(
7481 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7482 consumeKey(/*handled=*/false,
7483 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7484 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7485
7486 // Since the window was removed, it loses focus, and the channel state will be reset.
7487 consumeKey(/*handled=*/true,
7488 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7489 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7490 mWindow->consumeFocusEvent(false);
7491 mWindow->assertNoEvents();
7492}
7493
7494TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7495 setFallback(AKEYCODE_B);
7496 mDispatcher->notifyKey(
7497 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7498
7499 // Do not handle this key event.
7500 consumeKey(/*handled=*/false,
7501 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7502 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7503 const auto [seq, event] = mWindow->receiveEvent();
7504 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7505 ASSERT_EQ(event->getType(), InputEventType::KEY);
7506 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7507 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7508 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7509
7510 // Remove the window now, which should generate a cancellations and make the window lose focus.
7511 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7512 consumeKey(/*handled=*/true,
7513 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7514 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7515 consumeKey(/*handled=*/true,
7516 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7517 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7518 mWindow->consumeFocusEvent(false);
7519
7520 // Finish the event by reporting it as handled.
7521 mWindow->finishEvent(*seq);
7522 mWindow->assertNoEvents();
7523}
7524
Garfield Tan1c7bc862020-01-28 13:24:04 -08007525class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7526protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007527 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7528 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007529
Chris Yea209fde2020-07-22 13:54:51 -07007530 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007531 sp<FakeWindowHandle> mWindow;
7532
7533 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007534 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007535
Prabir Pradhandae52792023-12-15 07:36:40 +00007536 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007537 setUpWindow();
7538 }
7539
7540 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007541 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007542 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007543
Vishnu Nair47074b82020-08-14 11:54:47 -07007544 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007545 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007546 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007547 mWindow->consumeFocusEvent(true);
7548 }
7549
Chris Ye2ad95392020-09-01 13:44:44 -07007550 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007551 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007552 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007553 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007554 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007555
7556 // Window should receive key down event.
7557 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7558 }
7559
7560 void expectKeyRepeatOnce(int32_t repeatCount) {
7561 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007562 mWindow->consumeKeyEvent(
7563 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007564 }
7565
Chris Ye2ad95392020-09-01 13:44:44 -07007566 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007567 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007568 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007569 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007570 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007571
7572 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007573 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007574 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007575 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007576
7577 void injectKeyRepeat(int32_t repeatCount) {
7578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7579 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7580 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7581 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007582};
7583
7584TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007585 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007586 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7587 expectKeyRepeatOnce(repeatCount);
7588 }
7589}
7590
7591TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007592 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007593 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7594 expectKeyRepeatOnce(repeatCount);
7595 }
Harry Cutts33476232023-01-30 19:57:29 +00007596 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007597 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007598 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7599 expectKeyRepeatOnce(repeatCount);
7600 }
7601}
7602
7603TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007604 sendAndConsumeKeyDown(/*deviceId=*/1);
7605 expectKeyRepeatOnce(/*repeatCount=*/1);
7606 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007607 mWindow->assertNoEvents();
7608}
7609
7610TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007611 sendAndConsumeKeyDown(/*deviceId=*/1);
7612 expectKeyRepeatOnce(/*repeatCount=*/1);
7613 sendAndConsumeKeyDown(/*deviceId=*/2);
7614 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007615 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007616 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007617 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007618 expectKeyRepeatOnce(/*repeatCount=*/2);
7619 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007620 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007621 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007622 mWindow->assertNoEvents();
7623}
7624
7625TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007626 sendAndConsumeKeyDown(/*deviceId=*/1);
7627 expectKeyRepeatOnce(/*repeatCount=*/1);
7628 sendAndConsumeKeyDown(/*deviceId=*/2);
7629 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007630 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007631 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007632 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007633 mWindow->assertNoEvents();
7634}
7635
liushenxiang42232912021-05-21 20:24:09 +08007636TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7637 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007638 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007639 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007640 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7641 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7642 mWindow->assertNoEvents();
7643}
7644
Garfield Tan1c7bc862020-01-28 13:24:04 -08007645TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007646 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007647 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007648 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007649 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7650 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007651 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007652 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007653 }
7654}
7655
7656TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007657 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007658 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007659
7660 std::unordered_set<int32_t> idSet;
7661 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007662 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7663 ASSERT_NE(nullptr, repeatEvent);
7664 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007665 EXPECT_EQ(idSet.end(), idSet.find(id));
7666 idSet.insert(id);
7667 }
7668}
7669
Hu Guofe3c8f12023-09-22 17:20:15 +08007670TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7671 injectKeyRepeat(0);
7672 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7673 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7674 expectKeyRepeatOnce(repeatCount);
7675 }
7676 injectKeyRepeat(1);
7677 // Expect repeatCount to be 3 instead of 1
7678 expectKeyRepeatOnce(3);
7679}
7680
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007681/* Test InputDispatcher for MultiDisplay */
7682class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7683public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007684 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007685 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007686
Chris Yea209fde2020-07-22 13:54:51 -07007687 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007688 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007689 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007690
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007691 // Set focus window for primary display, but focused display would be second one.
7692 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007693 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007694 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7695
Vishnu Nair958da932020-08-21 17:12:37 -07007696 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007697 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007698
Chris Yea209fde2020-07-22 13:54:51 -07007699 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007700 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007701 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007702 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007703 // Set focus display to second one.
7704 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7705 // Set focus window for second display.
7706 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007707 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007708 mDispatcher->onWindowInfosChanged(
7709 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007710 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007711 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007712 }
7713
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007714 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007715 InputDispatcherTest::TearDown();
7716
Chris Yea209fde2020-07-22 13:54:51 -07007717 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007718 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007719 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007720 windowInSecondary.clear();
7721 }
7722
7723protected:
Chris Yea209fde2020-07-22 13:54:51 -07007724 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007725 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007726 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007727 sp<FakeWindowHandle> windowInSecondary;
7728};
7729
7730TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7731 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007735 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007736 windowInSecondary->assertNoEvents();
7737
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007738 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007740 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007742 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007743 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007744}
7745
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007746TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007747 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007749 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007750 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007751 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007752 windowInSecondary->assertNoEvents();
7753
7754 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007757 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007758 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007759
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007760 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007761 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007762
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007763 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007764 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007765
7766 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007767 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007768 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007769 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007770 windowInSecondary->assertNoEvents();
7771}
7772
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007773// Test per-display input monitors for motion event.
7774TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007775 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007776 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007777 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007778 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007779
7780 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007782 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007783 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007784 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007785 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007786 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007787 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007788
7789 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007791 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007793 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007794 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007795 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007796 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007797
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007798 // Lift up the touch from the second display
7799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007800 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7802 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7803 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7804
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007805 // Test inject a non-pointer motion event.
7806 // If specific a display, it will dispatch to the focused window of particular display,
7807 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007809 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007811 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007812 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007813 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007814 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007815}
7816
7817// Test per-display input monitors for key event.
7818TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007819 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007820 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007821 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007822 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007823 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007824
7825 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007827 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007828 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007829 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007830 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007831 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007832}
7833
Vishnu Nair958da932020-08-21 17:12:37 -07007834TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7835 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007836 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007837 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007838 mDispatcher->onWindowInfosChanged(
7839 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7840 *windowInSecondary->getInfo()},
7841 {},
7842 0,
7843 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007844 setFocusedWindow(secondWindowInPrimary);
7845 windowInPrimary->consumeFocusEvent(false);
7846 secondWindowInPrimary->consumeFocusEvent(true);
7847
7848 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7850 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007851 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007852 windowInPrimary->assertNoEvents();
7853 windowInSecondary->assertNoEvents();
7854 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7855}
7856
Arthur Hungdfd528e2021-12-08 13:23:04 +00007857TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7858 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007859 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007860 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007861 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007862
7863 // Test touch down on primary display.
7864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007865 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7867 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7868 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7869
7870 // Test touch down on second display.
7871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007872 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007873 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7874 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7875 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7876
7877 // Trigger cancel touch.
7878 mDispatcher->cancelCurrentTouch();
7879 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7880 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7881 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7882 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7883
7884 // Test inject a move motion event, no window/monitor should receive the event.
7885 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007886 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007887 ADISPLAY_ID_DEFAULT, {110, 200}))
7888 << "Inject motion event should return InputEventInjectionResult::FAILED";
7889 windowInPrimary->assertNoEvents();
7890 monitorInPrimary.assertNoEvents();
7891
7892 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007893 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007894 SECOND_DISPLAY_ID, {110, 200}))
7895 << "Inject motion event should return InputEventInjectionResult::FAILED";
7896 windowInSecondary->assertNoEvents();
7897 monitorInSecondary.assertNoEvents();
7898}
7899
Hu Guocb134f12023-12-23 13:42:44 +00007900/**
7901 * Send a key to the primary display and to the secondary display.
7902 * Then cause the key on the primary display to be canceled by sending in a stale key.
7903 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7904 * does not get canceled.
7905 */
7906TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7907 // Send a key down on primary display
7908 mDispatcher->notifyKey(
7909 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7910 .displayId(ADISPLAY_ID_DEFAULT)
7911 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7912 .build());
7913 windowInPrimary->consumeKeyEvent(
7914 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7915 windowInSecondary->assertNoEvents();
7916
7917 // Send a key down on second display
7918 mDispatcher->notifyKey(
7919 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7920 .displayId(SECOND_DISPLAY_ID)
7921 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7922 .build());
7923 windowInSecondary->consumeKeyEvent(
7924 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7925 windowInPrimary->assertNoEvents();
7926
7927 // Send a valid key up event on primary display that will be dropped because it is stale
7928 NotifyKeyArgs staleKeyUp =
7929 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7930 .displayId(ADISPLAY_ID_DEFAULT)
7931 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7932 .build();
7933 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7934 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7935 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7936 mDispatcher->notifyKey(staleKeyUp);
7937
7938 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7939 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7940 // receive any events.
7941 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7942 WithDisplayId(ADISPLAY_ID_DEFAULT),
7943 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7944 windowInSecondary->assertNoEvents();
7945}
7946
7947/**
7948 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7949 */
7950TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7951 // Send touch down on primary display.
7952 mDispatcher->notifyMotion(
7953 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7954 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7955 .displayId(ADISPLAY_ID_DEFAULT)
7956 .build());
7957 windowInPrimary->consumeMotionEvent(
7958 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7959 windowInSecondary->assertNoEvents();
7960
7961 // Send touch down on second display.
7962 mDispatcher->notifyMotion(
7963 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7964 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7965 .displayId(SECOND_DISPLAY_ID)
7966 .build());
7967 windowInPrimary->assertNoEvents();
7968 windowInSecondary->consumeMotionEvent(
7969 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7970
7971 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7972 NotifyMotionArgs staleMotionUp =
7973 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7974 .displayId(ADISPLAY_ID_DEFAULT)
7975 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7976 .build();
7977 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7978 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7979 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7980 mDispatcher->notifyMotion(staleMotionUp);
7981
7982 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7983 // events, where we would cancel the current keys instead.
7984 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7985 windowInSecondary->assertNoEvents();
7986}
7987
Jackal Guof9696682018-10-05 12:23:23 +08007988class InputFilterTest : public InputDispatcherTest {
7989protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007990 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7991 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007992 NotifyMotionArgs motionArgs;
7993
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007994 motionArgs =
7995 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007996 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007997 motionArgs =
7998 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007999 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008000 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008001 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008002 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008003 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08008004 } else {
8005 mFakePolicy->assertFilterInputEventWasNotCalled();
8006 }
8007 }
8008
8009 void testNotifyKey(bool expectToBeFiltered) {
8010 NotifyKeyArgs keyArgs;
8011
8012 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008013 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008014 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008015 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008016 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008017
8018 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08008019 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008020 } else {
8021 mFakePolicy->assertFilterInputEventWasNotCalled();
8022 }
8023 }
8024};
8025
8026// Test InputFilter for MotionEvent
8027TEST_F(InputFilterTest, MotionEvent_InputFilter) {
8028 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008029 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
8030 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008031
8032 // Enable InputFilter
8033 mDispatcher->setInputFilterEnabled(true);
8034 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008035 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
8036 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008037
8038 // Disable InputFilter
8039 mDispatcher->setInputFilterEnabled(false);
8040 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008041 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
8042 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008043}
8044
8045// Test InputFilter for KeyEvent
8046TEST_F(InputFilterTest, KeyEvent_InputFilter) {
8047 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008048 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008049
8050 // Enable InputFilter
8051 mDispatcher->setInputFilterEnabled(true);
8052 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008053 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008054
8055 // Disable InputFilter
8056 mDispatcher->setInputFilterEnabled(false);
8057 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008058 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008059}
8060
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008061// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
8062// logical display coordinate space.
8063TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
8064 ui::Transform firstDisplayTransform;
8065 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8066 ui::Transform secondDisplayTransform;
8067 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
8068
8069 std::vector<gui::DisplayInfo> displayInfos(2);
8070 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
8071 displayInfos[0].transform = firstDisplayTransform;
8072 displayInfos[1].displayId = SECOND_DISPLAY_ID;
8073 displayInfos[1].transform = secondDisplayTransform;
8074
Patrick Williamsd828f302023-04-28 17:52:08 -05008075 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008076
8077 // Enable InputFilter
8078 mDispatcher->setInputFilterEnabled(true);
8079
8080 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008081 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
8082 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008083}
8084
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008085class InputFilterInjectionPolicyTest : public InputDispatcherTest {
8086protected:
8087 virtual void SetUp() override {
8088 InputDispatcherTest::SetUp();
8089
8090 /**
8091 * We don't need to enable input filter to test the injected event policy, but we enabled it
8092 * here to make the tests more realistic, since this policy only matters when inputfilter is
8093 * on.
8094 */
8095 mDispatcher->setInputFilterEnabled(true);
8096
8097 std::shared_ptr<InputApplicationHandle> application =
8098 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008099 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8100 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008101
8102 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8103 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008104 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008105 setFocusedWindow(mWindow);
8106 mWindow->consumeFocusEvent(true);
8107 }
8108
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008109 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8110 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008111 KeyEvent event;
8112
8113 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8114 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8115 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008116 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008117 const int32_t additionalPolicyFlags =
8118 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008120 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008121 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008122 policyFlags | additionalPolicyFlags));
8123
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008124 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008125 }
8126
8127 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8128 int32_t flags) {
8129 MotionEvent event;
8130 PointerProperties pointerProperties[1];
8131 PointerCoords pointerCoords[1];
8132 pointerProperties[0].clear();
8133 pointerProperties[0].id = 0;
8134 pointerCoords[0].clear();
8135 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8136 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8137
8138 ui::Transform identityTransform;
8139 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8140 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8141 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8142 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8143 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008144 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008145 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008146 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008147
8148 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008150 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008151 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008152 policyFlags | additionalPolicyFlags));
8153
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008154 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008155 }
8156
8157private:
8158 sp<FakeWindowHandle> mWindow;
8159};
8160
8161TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008162 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8163 // filter. Without it, the event will no different from a regularly injected event, and the
8164 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008165 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8166 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008167}
8168
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008169TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008170 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008171 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008172 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8173}
8174
8175TEST_F(InputFilterInjectionPolicyTest,
8176 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8177 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008178 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008179 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008180}
8181
8182TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008183 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8184 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008185}
8186
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008187class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8188protected:
8189 virtual void SetUp() override {
8190 InputDispatcherTest::SetUp();
8191
8192 std::shared_ptr<FakeApplicationHandle> application =
8193 std::make_shared<FakeApplicationHandle>();
8194 application->setDispatchingTimeout(100ms);
8195 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8196 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008197 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008198 mWindow->setDispatchingTimeout(100ms);
8199 mWindow->setFocusable(true);
8200
8201 // Set focused application.
8202 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8203
8204 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8205 setFocusedWindow(mWindow);
8206 mWindow->consumeFocusEvent(true);
8207 }
8208
8209 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8210 nsecs_t eventTime) {
8211 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8212 .displayId(displayId)
8213 .eventTime(eventTime)
8214 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8215 .build());
8216 mWindow->consumeMotionEvent(WithMotionAction(action));
8217 }
8218
8219private:
8220 sp<FakeWindowHandle> mWindow;
8221};
8222
8223TEST_F_WITH_FLAGS(
8224 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8225 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8226 rate_limit_user_activity_poke_in_dispatcher))) {
8227 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8228
8229 // First event of type TOUCH. Should poke.
8230 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8231 milliseconds_to_nanoseconds(50));
8232 mFakePolicy->assertUserActivityPoked(
8233 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8234
8235 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8236 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8237 milliseconds_to_nanoseconds(130));
8238 mFakePolicy->assertUserActivityPoked(
8239 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8240
8241 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8242 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8243 milliseconds_to_nanoseconds(135));
8244 mFakePolicy->assertUserActivityPoked(
8245 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8246
8247 // Within 50ns of previous TOUCH event. Should NOT poke.
8248 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8249 milliseconds_to_nanoseconds(140));
8250 mFakePolicy->assertUserActivityNotPoked();
8251
8252 // Within 50ns of previous OTHER event. Should NOT poke.
8253 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8254 milliseconds_to_nanoseconds(150));
8255 mFakePolicy->assertUserActivityNotPoked();
8256
8257 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8258 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8259 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8260 milliseconds_to_nanoseconds(160));
8261 mFakePolicy->assertUserActivityNotPoked();
8262
8263 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8264 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8265 milliseconds_to_nanoseconds(200));
8266 mFakePolicy->assertUserActivityPoked(
8267 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8268
8269 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8270 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8271 milliseconds_to_nanoseconds(300));
8272 mFakePolicy->assertUserActivityPoked(
8273 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8274
8275 // Assert that there's no more user activity poke event.
8276 mFakePolicy->assertUserActivityNotPoked();
8277}
8278
8279TEST_F_WITH_FLAGS(
8280 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8281 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8282 rate_limit_user_activity_poke_in_dispatcher))) {
8283 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8284 milliseconds_to_nanoseconds(200));
8285 mFakePolicy->assertUserActivityPoked(
8286 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8287
8288 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8289 milliseconds_to_nanoseconds(280));
8290 mFakePolicy->assertUserActivityNotPoked();
8291
8292 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8293 milliseconds_to_nanoseconds(340));
8294 mFakePolicy->assertUserActivityPoked(
8295 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8296}
8297
8298TEST_F_WITH_FLAGS(
8299 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8300 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8301 rate_limit_user_activity_poke_in_dispatcher))) {
8302 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8303
8304 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8305 mFakePolicy->assertUserActivityPoked();
8306
8307 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8308 mFakePolicy->assertUserActivityPoked();
8309}
8310
chaviwfd6d3512019-03-25 13:23:49 -07008311class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008312 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008313 InputDispatcherTest::SetUp();
8314
Chris Yea209fde2020-07-22 13:54:51 -07008315 std::shared_ptr<FakeApplicationHandle> application =
8316 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008317 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008318 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008319 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008320
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008321 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008322 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008323 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008324
8325 // Set focused application.
8326 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008327 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008328
8329 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008330 mDispatcher->onWindowInfosChanged(
8331 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008332 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008333 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008334 }
8335
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008336 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008337 InputDispatcherTest::TearDown();
8338
8339 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008340 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008341 }
8342
8343protected:
8344 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008345 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008346 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008347};
8348
8349// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8350// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8351// the onPointerDownOutsideFocus callback.
8352TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008355 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008357 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008358
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008359 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008360 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8361}
8362
8363// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8364// DOWN on the window that doesn't have focus. Ensure no window received the
8365// onPointerDownOutsideFocus callback.
8366TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008368 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8369 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008370 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008371 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008372
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008373 ASSERT_TRUE(mDispatcher->waitForIdle());
8374 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008375}
8376
8377// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8378// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8379TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008381 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008382 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008383 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008384
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008385 ASSERT_TRUE(mDispatcher->waitForIdle());
8386 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008387}
8388
8389// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8390// DOWN on the window that already has focus. Ensure no window received the
8391// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008392TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008394 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008395 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008397 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008398
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008399 ASSERT_TRUE(mDispatcher->waitForIdle());
8400 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008401}
8402
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008403// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8404// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8405TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8406 const MotionEvent event =
8407 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8408 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008409 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008410 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8411 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8414 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8415
8416 ASSERT_TRUE(mDispatcher->waitForIdle());
8417 mFakePolicy->assertOnPointerDownWasNotCalled();
8418 // Ensure that the unfocused window did not receive any FOCUS events.
8419 mUnfocusedWindow->assertNoEvents();
8420}
8421
chaviwaf87b3e2019-10-01 16:59:28 -07008422// These tests ensures we can send touch events to a single client when there are multiple input
8423// windows that point to the same client token.
8424class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8425 virtual void SetUp() override {
8426 InputDispatcherTest::SetUp();
8427
Chris Yea209fde2020-07-22 13:54:51 -07008428 std::shared_ptr<FakeApplicationHandle> application =
8429 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008430 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8431 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008432 mWindow1->setFrame(Rect(0, 0, 100, 100));
8433
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008434 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008435 mWindow2->setFrame(Rect(100, 100, 200, 200));
8436
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008437 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008438 }
8439
8440protected:
8441 sp<FakeWindowHandle> mWindow1;
8442 sp<FakeWindowHandle> mWindow2;
8443
8444 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008445 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008446 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8447 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008448 }
8449
8450 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8451 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008452 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008453 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008454 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008455 ASSERT_NE(nullptr, motionEvent);
8456 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008457
8458 for (size_t i = 0; i < points.size(); i++) {
8459 float expectedX = points[i].x;
8460 float expectedY = points[i].y;
8461
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008462 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008463 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008464 << ", got " << motionEvent->getX(i);
8465 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008466 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008467 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008468 }
8469 }
chaviw9eaa22c2020-07-01 16:21:27 -07008470
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008471 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8472 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008473 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008474 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8475 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008476
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008477 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008478 }
chaviwaf87b3e2019-10-01 16:59:28 -07008479};
8480
8481TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8482 // Touch Window 1
8483 PointF touchedPoint = {10, 10};
8484 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008485 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008486
8487 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008488 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008489
8490 // Touch Window 2
8491 touchedPoint = {150, 150};
8492 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008493 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008494}
8495
chaviw9eaa22c2020-07-01 16:21:27 -07008496TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8497 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008498 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008499 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008500
8501 // Touch Window 1
8502 PointF touchedPoint = {10, 10};
8503 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008504 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008505 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008506 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008507
8508 // Touch Window 2
8509 touchedPoint = {150, 150};
8510 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008511 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8512 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008513
chaviw9eaa22c2020-07-01 16:21:27 -07008514 // Update the transform so rotation is set
8515 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008516 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008517 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008518 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008519}
8520
chaviw9eaa22c2020-07-01 16:21:27 -07008521TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008522 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008523 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008524
8525 // Touch Window 1
8526 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8527 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008528 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008529
8530 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008531 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8532 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8533 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008534 touchedPoints.push_back(PointF{150, 150});
8535 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008536 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008537
chaviw9eaa22c2020-07-01 16:21:27 -07008538 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008539 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008540 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008541
chaviw9eaa22c2020-07-01 16:21:27 -07008542 // Update the transform so rotation is set for Window 2
8543 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008544 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008545 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008546 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008547}
8548
chaviw9eaa22c2020-07-01 16:21:27 -07008549TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008550 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008551 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008552
8553 // Touch Window 1
8554 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8555 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008556 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008557
8558 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008559 touchedPoints.push_back(PointF{150, 150});
8560 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008561
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008562 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008563
8564 // Move both windows
8565 touchedPoints = {{20, 20}, {175, 175}};
8566 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8567 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8568
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008569 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008570
chaviw9eaa22c2020-07-01 16:21:27 -07008571 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008572 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008573 expectedPoints.pop_back();
8574
8575 // Touch Window 2
8576 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008577 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008578 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008579 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008580
8581 // Move both windows
8582 touchedPoints = {{20, 20}, {175, 175}};
8583 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8584 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8585
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008586 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008587}
8588
8589TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8590 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008591 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008592
8593 // Touch Window 1
8594 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8595 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008596 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008597
8598 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008599 touchedPoints.push_back(PointF{150, 150});
8600 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008601
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008602 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008603
8604 // Move both windows
8605 touchedPoints = {{20, 20}, {175, 175}};
8606 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8607 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8608
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008609 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008610}
8611
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008612/**
8613 * When one of the windows is slippery, the touch should not slip into the other window with the
8614 * same input channel.
8615 */
8616TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8617 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008618 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008619
8620 // Touch down in window 1
8621 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8622 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8623 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8624
8625 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8626 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8627 // getting generated.
8628 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8629 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8630
8631 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8632}
8633
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008634/**
8635 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8636 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8637 * that the pointer is hovering over may have a different transform.
8638 */
8639TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008640 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008641
8642 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8644 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8645 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008646 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8647 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008648 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8650 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8651 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008652 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008653 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008654 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8655}
8656
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008657class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8658 virtual void SetUp() override {
8659 InputDispatcherTest::SetUp();
8660
Chris Yea209fde2020-07-22 13:54:51 -07008661 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008662 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008663 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8664 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008665 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008666 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008667 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008668
8669 // Set focused application.
8670 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8671
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008672 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008673 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008674 mWindow->consumeFocusEvent(true);
8675 }
8676
8677 virtual void TearDown() override {
8678 InputDispatcherTest::TearDown();
8679 mWindow.clear();
8680 }
8681
8682protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008683 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008684 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008685 sp<FakeWindowHandle> mWindow;
8686 static constexpr PointF WINDOW_LOCATION = {20, 20};
8687
8688 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008689 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8690 .x(WINDOW_LOCATION.x)
8691 .y(WINDOW_LOCATION.y);
8692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8693 .pointer(touchingPointer)
8694 .build());
8695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8696 .pointer(touchingPointer)
8697 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008698 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008699
8700 sp<FakeWindowHandle> addSpyWindow() {
8701 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008702 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008703 spy->setTrustedOverlay(true);
8704 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008705 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008706 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008707 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008708 return spy;
8709 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008710};
8711
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008712// Send a tap and respond, which should not cause an ANR.
8713TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8714 tapOnWindow();
8715 mWindow->consumeMotionDown();
8716 mWindow->consumeMotionUp();
8717 ASSERT_TRUE(mDispatcher->waitForIdle());
8718 mFakePolicy->assertNotifyAnrWasNotCalled();
8719}
8720
8721// Send a regular key and respond, which should not cause an ANR.
8722TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008724 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8725 ASSERT_TRUE(mDispatcher->waitForIdle());
8726 mFakePolicy->assertNotifyAnrWasNotCalled();
8727}
8728
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008729TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8730 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008731 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008732 mWindow->consumeFocusEvent(false);
8733
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008734 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008735 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8736 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008737 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008739 // Key will not go to window because we have no focused window.
8740 // The 'no focused window' ANR timer should start instead.
8741
8742 // Now, the focused application goes away.
8743 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8744 // The key should get dropped and there should be no ANR.
8745
8746 ASSERT_TRUE(mDispatcher->waitForIdle());
8747 mFakePolicy->assertNotifyAnrWasNotCalled();
8748}
8749
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008750// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008751// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8752// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008753TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008755 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008756 WINDOW_LOCATION));
8757
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008758 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008759 ASSERT_TRUE(sequenceNum);
8760 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008761 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008762
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008763 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008764 mWindow->consumeMotionEvent(
8765 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008766 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008767 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008768}
8769
8770// Send a key to the app and have the app not respond right away.
8771TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8772 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008774 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008775 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008776 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008777 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008778 ASSERT_TRUE(mDispatcher->waitForIdle());
8779}
8780
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008781// We have a focused application, but no focused window
8782TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008783 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008784 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008785 mWindow->consumeFocusEvent(false);
8786
8787 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008790 WINDOW_LOCATION));
8791 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8792 mDispatcher->waitForIdle();
8793 mFakePolicy->assertNotifyAnrWasNotCalled();
8794
8795 // Once a focused event arrives, we get an ANR for this application
8796 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8797 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008798 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008799 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008800 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008801 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008802 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008803 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008804 ASSERT_TRUE(mDispatcher->waitForIdle());
8805}
8806
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008807/**
8808 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8809 * there will not be an ANR.
8810 */
8811TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8812 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008813 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008814 mWindow->consumeFocusEvent(false);
8815
8816 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008817 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8818 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008819 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8820 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8821
8822 // Define a valid key down event that is stale (too old).
8823 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008824 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008825 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008826
Hu Guofe3c8f12023-09-22 17:20:15 +08008827 const int32_t policyFlags =
8828 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008829
8830 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008831 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008832 InputEventInjectionSync::WAIT_FOR_RESULT,
8833 INJECT_EVENT_TIMEOUT, policyFlags);
8834 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8835 << "Injection should fail because the event is stale";
8836
8837 ASSERT_TRUE(mDispatcher->waitForIdle());
8838 mFakePolicy->assertNotifyAnrWasNotCalled();
8839 mWindow->assertNoEvents();
8840}
8841
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008842// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008843// Make sure that we don't notify policy twice about the same ANR.
8844TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008845 const std::chrono::duration appTimeout = 400ms;
8846 mApplication->setDispatchingTimeout(appTimeout);
8847 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8848
Vishnu Nair47074b82020-08-14 11:54:47 -07008849 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008850 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008851 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008852
8853 // Once a focused event arrives, we get an ANR for this application
8854 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8855 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008856 const std::chrono::duration eventInjectionTimeout = 100ms;
8857 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008858 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008859 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008860 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8861 /*allowKeyRepeat=*/false);
8862 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8863 << "result=" << ftl::enum_string(result);
8864 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8865 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8866 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8867 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008868
Vishnu Naire4df8752022-09-08 09:17:55 -07008869 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008870 // ANR should not be raised again. It is up to policy to do that if it desires.
8871 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008872
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008873 // If we now get a focused window, the ANR should stop, but the policy handles that via
8874 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008875 ASSERT_TRUE(mDispatcher->waitForIdle());
8876}
8877
8878// We have a focused application, but no focused window
8879TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008880 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008881 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008882 mWindow->consumeFocusEvent(false);
8883
8884 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008885 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008886
Vishnu Naire4df8752022-09-08 09:17:55 -07008887 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8888 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008889
8890 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008891 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008892 ASSERT_TRUE(mDispatcher->waitForIdle());
8893 mWindow->assertNoEvents();
8894}
8895
8896/**
8897 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8898 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8899 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8900 * the ANR mechanism should still work.
8901 *
8902 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8903 * DOWN event, while not responding on the second one.
8904 */
8905TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8906 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008907 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008908 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8909 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8910 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008911 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008912
8913 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008914 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008915 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8916 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8917 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008918 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008919
8920 // We have now sent down and up. Let's consume first event and then ANR on the second.
8921 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8922 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008923 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008924}
8925
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008926// A spy window can receive an ANR
8927TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8928 sp<FakeWindowHandle> spy = addSpyWindow();
8929
8930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008931 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008932 WINDOW_LOCATION));
8933 mWindow->consumeMotionDown();
8934
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008935 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008936 ASSERT_TRUE(sequenceNum);
8937 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008938 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008939
8940 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008941 spy->consumeMotionEvent(
8942 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008943 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008944 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008945}
8946
8947// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008948// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008949TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8950 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008951
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008952 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008953 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008954 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008956
8957 // Stuck on the ACTION_UP
8958 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008959 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008960
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008961 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008962 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008963 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8964 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008965
8966 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8967 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008968 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008969 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008970 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008971}
8972
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008973// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008974// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008975TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8976 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008977
8978 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008979 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8980 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008981
8982 mWindow->consumeMotionDown();
8983 // Stuck on the ACTION_UP
8984 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008985 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008986
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008987 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008988 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008989 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8990 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008991
8992 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8993 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008994 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008995 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008996 spy->assertNoEvents();
8997}
8998
8999TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009000 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009001
Prabir Pradhanfb549072023-10-05 19:17:36 +00009002 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009003
9004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009005 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009006 WINDOW_LOCATION));
9007
9008 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
9009 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
9010 ASSERT_TRUE(consumeSeq);
9011
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009012 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
9013 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009014
9015 monitor.finishEvent(*consumeSeq);
9016 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
9017
9018 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009019 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009020}
9021
9022// If a window is unresponsive, then you get anr. if the window later catches up and starts to
9023// process events, you don't get an anr. When the window later becomes unresponsive again, you
9024// get an ANR again.
9025// 1. tap -> block on ACTION_UP -> receive ANR
9026// 2. consume all pending events (= queue becomes healthy again)
9027// 3. tap again -> block on ACTION_UP again -> receive ANR second time
9028TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
9029 tapOnWindow();
9030
9031 mWindow->consumeMotionDown();
9032 // Block on ACTION_UP
9033 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009034 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009035 mWindow->consumeMotionUp(); // Now the connection should be healthy again
9036 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009037 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009038 mWindow->assertNoEvents();
9039
9040 tapOnWindow();
9041 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009042 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009043 mWindow->consumeMotionUp();
9044
9045 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009046 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009047 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009048 mWindow->assertNoEvents();
9049}
9050
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009051// If a connection remains unresponsive for a while, make sure policy is only notified once about
9052// it.
9053TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009056 WINDOW_LOCATION));
9057
9058 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009059 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009060 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009061 // 'notifyConnectionUnresponsive' should only be called once per connection
9062 mFakePolicy->assertNotifyAnrWasNotCalled();
9063 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009064 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009065 mWindow->consumeMotionEvent(
9066 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009067 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009068 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009069 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009070 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009071}
9072
9073/**
9074 * 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 -07009075 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009076 */
9077TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009078 // The timeouts in this test are established by relying on the fact that the "key waiting for
9079 // events timeout" is equal to 500ms.
9080 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009081 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009082 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009083
9084 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009085 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009086 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009087 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009088 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009089
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009090 // Don't finish the events yet, and send a key
9091 mDispatcher->notifyKey(
9092 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9093 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9094 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009095 // Key will not be sent to the window, yet, because the window is still processing events
9096 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009097 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009098 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009099
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009100 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009101 // if we wait long enough though, dispatcher will give up, and still send the key
9102 // to the focused window, even though we have not yet finished the motion event
9103 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9104 mWindow->finishEvent(*downSequenceNum);
9105 mWindow->finishEvent(*upSequenceNum);
9106}
9107
9108/**
9109 * If a window is processing a motion event, and then a key event comes in, the key event should
9110 * not go to the focused window until the motion is processed.
9111 * If then a new motion comes in, then the pending key event should be going to the currently
9112 * focused window right away.
9113 */
9114TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009115 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9116 // The timeouts in this test are established by relying on the fact that the "key waiting for
9117 // events timeout" is equal to 500ms.
9118 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009119 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009120 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009121
9122 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009123 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009124 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009125 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009126 ASSERT_TRUE(upSequenceNum);
9127 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009128 mDispatcher->notifyKey(
9129 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9130 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9131 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009132 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009133 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009134
9135 // Now tap down again. It should cause the pending key to go to the focused window right away.
9136 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009137 // Now that we tapped, we should receive the key immediately.
9138 // Since there's still room for slowness, we use 200ms, which is much less than
9139 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9140 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9141 ASSERT_NE(nullptr, keyEvent);
9142 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9143 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9144 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9145 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009146 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9147 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009148 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9149 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009150 mWindow->assertNoEvents();
9151}
9152
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009153/**
9154 * Send an event to the app and have the app not respond right away.
9155 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9156 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9157 * At some point, the window becomes responsive again.
9158 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9159 */
9160TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9162 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9163 .build());
9164
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009165 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009166 ASSERT_TRUE(sequenceNum);
9167 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9168 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9169
9170 mWindow->finishEvent(*sequenceNum);
9171 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9172 ASSERT_TRUE(mDispatcher->waitForIdle());
9173 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9174
9175 // Now that the window is responsive, let's continue the gesture.
9176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9177 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9178 .build());
9179
9180 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9181 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9182 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9183 .build());
9184
9185 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9186 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9187 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9188 .build());
9189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9190 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9191 .build());
9192 // We already canceled this pointer, so the window shouldn't get any new events.
9193 mWindow->assertNoEvents();
9194
9195 // Start another one.
9196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9197 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9198 .build());
9199 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9200}
9201
Prabir Pradhanfc364722024-02-08 17:51:20 +00009202// Send an event to the app and have the app not respond right away. Then remove the app window.
9203// When the window is removed, the dispatcher will cancel the events for that window.
9204// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9205TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9206 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9207 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9208 {WINDOW_LOCATION}));
9209
9210 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9211 ASSERT_TRUE(sequenceNum);
9212
9213 // Remove the window, but the input channel should remain alive.
9214 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9215
9216 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9217 // Since the window was removed, Dispatcher does not know the PID associated with the window
9218 // anymore, so the policy is notified without the PID.
9219 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9220 /*pid=*/std::nullopt);
9221
9222 mWindow->finishEvent(*sequenceNum);
9223 // The cancellation was generated when the window was removed, along with the focus event.
9224 mWindow->consumeMotionEvent(
9225 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9226 mWindow->consumeFocusEvent(false);
9227 ASSERT_TRUE(mDispatcher->waitForIdle());
9228 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9229}
9230
9231// Send an event to the app and have the app not respond right away. Wait for the policy to be
9232// notified of the unresponsive window, then remove the app window.
9233TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9234 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9235 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9236 {WINDOW_LOCATION}));
9237
9238 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9239 ASSERT_TRUE(sequenceNum);
9240 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9241 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9242
9243 // Remove the window, but the input channel should remain alive.
9244 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9245
9246 mWindow->finishEvent(*sequenceNum);
9247 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9248 mWindow->consumeMotionEvent(
9249 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9250 mWindow->consumeFocusEvent(false);
9251 ASSERT_TRUE(mDispatcher->waitForIdle());
9252 // Since the window was removed, Dispatcher does not know the PID associated with the window
9253 // becoming responsive, so the policy is notified without the PID.
9254 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9255}
9256
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009257class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9258 virtual void SetUp() override {
9259 InputDispatcherTest::SetUp();
9260
Chris Yea209fde2020-07-22 13:54:51 -07009261 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009262 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009263 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9264 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009265 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009266 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009267 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009268
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009269 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9270 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009271 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009272 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009273
9274 // Set focused application.
9275 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009276 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009277
9278 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009279 mDispatcher->onWindowInfosChanged(
9280 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009281 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009282 mFocusedWindow->consumeFocusEvent(true);
9283 }
9284
9285 virtual void TearDown() override {
9286 InputDispatcherTest::TearDown();
9287
9288 mUnfocusedWindow.clear();
9289 mFocusedWindow.clear();
9290 }
9291
9292protected:
Chris Yea209fde2020-07-22 13:54:51 -07009293 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009294 sp<FakeWindowHandle> mUnfocusedWindow;
9295 sp<FakeWindowHandle> mFocusedWindow;
9296 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9297 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9298 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9299
9300 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9301
9302 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9303
9304private:
9305 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009308 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009310 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009311 location));
9312 }
9313};
9314
9315// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9316// should be ANR'd first.
9317TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009319 injectMotionEvent(*mDispatcher,
9320 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9321 AINPUT_SOURCE_TOUCHSCREEN)
9322 .pointer(PointerBuilder(0, ToolType::FINGER)
9323 .x(FOCUSED_WINDOW_LOCATION.x)
9324 .y(FOCUSED_WINDOW_LOCATION.y))
9325 .build()));
9326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9327 injectMotionEvent(*mDispatcher,
9328 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9329 AINPUT_SOURCE_TOUCHSCREEN)
9330 .pointer(PointerBuilder(0, ToolType::FINGER)
9331 .x(FOCUSED_WINDOW_LOCATION.x)
9332 .y(FOCUSED_WINDOW_LOCATION.y))
9333 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009334 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009335 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009336 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009337 // We consumed all events, so no ANR
9338 ASSERT_TRUE(mDispatcher->waitForIdle());
9339 mFakePolicy->assertNotifyAnrWasNotCalled();
9340
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009341 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009342 injectMotionEvent(*mDispatcher,
9343 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9344 AINPUT_SOURCE_TOUCHSCREEN)
9345 .pointer(PointerBuilder(0, ToolType::FINGER)
9346 .x(FOCUSED_WINDOW_LOCATION.x)
9347 .y(FOCUSED_WINDOW_LOCATION.y))
9348 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009349 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009350 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009351
9352 const std::chrono::duration timeout =
9353 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009354 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009355
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009356 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009357 mFocusedWindow->consumeMotionDown();
9358 // This cancel is generated because the connection was unresponsive
9359 mFocusedWindow->consumeMotionCancel();
9360 mFocusedWindow->assertNoEvents();
9361 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009362 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009363 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9364 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009365 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009366}
9367
9368// If we have 2 windows with identical timeouts that are both unresponsive,
9369// it doesn't matter which order they should have ANR.
9370// But we should receive ANR for both.
9371TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9372 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009373 mUnfocusedWindow->setDispatchingTimeout(
9374 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009375 mDispatcher->onWindowInfosChanged(
9376 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009377
9378 tapOnFocusedWindow();
9379 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009380 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009381 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9382 mFocusedWindow->getDispatchingTimeout(
9383 DISPATCHING_TIMEOUT)),
9384 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9385
9386 ASSERT_THAT(anrConnectionTokens,
9387 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9388 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009389
9390 ASSERT_TRUE(mDispatcher->waitForIdle());
9391 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009392
9393 mFocusedWindow->consumeMotionDown();
9394 mFocusedWindow->consumeMotionUp();
9395 mUnfocusedWindow->consumeMotionOutside();
9396
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009397 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9398 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009399
9400 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009401 ASSERT_THAT(responsiveTokens,
9402 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9403 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009404 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009405}
9406
9407// If a window is already not responding, the second tap on the same window should be ignored.
9408// We should also log an error to account for the dropped event (not tested here).
9409// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9410TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9411 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009412 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009413 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009414 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009415 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009416 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009417 ASSERT_TRUE(upEventSequenceNum);
9418 const std::chrono::duration timeout =
9419 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009420 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009421
9422 // Tap once again
9423 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009424 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009426 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009427 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009428 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009429 FOCUSED_WINDOW_LOCATION));
9430 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9431 // valid touch target
9432 mUnfocusedWindow->assertNoEvents();
9433
9434 // Consume the first tap
9435 mFocusedWindow->finishEvent(*downEventSequenceNum);
9436 mFocusedWindow->finishEvent(*upEventSequenceNum);
9437 ASSERT_TRUE(mDispatcher->waitForIdle());
9438 // The second tap did not go to the focused window
9439 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009440 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009441 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9442 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009443 mFakePolicy->assertNotifyAnrWasNotCalled();
9444}
9445
9446// If you tap outside of all windows, there will not be ANR
9447TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009448 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009449 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009450 LOCATION_OUTSIDE_ALL_WINDOWS));
9451 ASSERT_TRUE(mDispatcher->waitForIdle());
9452 mFakePolicy->assertNotifyAnrWasNotCalled();
9453}
9454
9455// Since the focused window is paused, tapping on it should not produce any events
9456TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9457 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009458 mDispatcher->onWindowInfosChanged(
9459 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009461 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009462 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009463 FOCUSED_WINDOW_LOCATION));
9464
9465 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9466 ASSERT_TRUE(mDispatcher->waitForIdle());
9467 // Should not ANR because the window is paused, and touches shouldn't go to it
9468 mFakePolicy->assertNotifyAnrWasNotCalled();
9469
9470 mFocusedWindow->assertNoEvents();
9471 mUnfocusedWindow->assertNoEvents();
9472}
9473
9474/**
9475 * 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 -07009476 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009477 * If a different window becomes focused at this time, the key should go to that window instead.
9478 *
9479 * Warning!!!
9480 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9481 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009482 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009483 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9484 *
9485 * If that value changes, this test should also change.
9486 */
9487TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9488 // Set a long ANR timeout to prevent it from triggering
9489 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009490 mDispatcher->onWindowInfosChanged(
9491 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009492
9493 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009494 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009495 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009496 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009497 ASSERT_TRUE(upSequenceNum);
9498 // Don't finish the events yet, and send a key
9499 // Injection will succeed because we will eventually give up and send the key to the focused
9500 // window even if motions are still being processed.
9501
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009502 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009503 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9504 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009506 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009507 // and the key remains pending, waiting for the touch events to be processed.
9508 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9509 // under the hood.
9510 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9511 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009512
9513 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009514 mFocusedWindow->setFocusable(false);
9515 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009516 mDispatcher->onWindowInfosChanged(
9517 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009518 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009519
9520 // Focus events should precede the key events
9521 mUnfocusedWindow->consumeFocusEvent(true);
9522 mFocusedWindow->consumeFocusEvent(false);
9523
9524 // Finish the tap events, which should unblock dispatcher
9525 mUnfocusedWindow->finishEvent(*downSequenceNum);
9526 mUnfocusedWindow->finishEvent(*upSequenceNum);
9527
9528 // Now that all queues are cleared and no backlog in the connections, the key event
9529 // can finally go to the newly focused "mUnfocusedWindow".
9530 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9531 mFocusedWindow->assertNoEvents();
9532 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009533 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009534}
9535
9536// When the touch stream is split across 2 windows, and one of them does not respond,
9537// then ANR should be raised and the touch should be canceled for the unresponsive window.
9538// The other window should not be affected by that.
9539TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9540 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009541 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9542 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9543 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009544 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009545
9546 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009547 mDispatcher->notifyMotion(
9548 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9549 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009550
9551 const std::chrono::duration timeout =
9552 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009553 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009554
9555 mUnfocusedWindow->consumeMotionDown();
9556 mFocusedWindow->consumeMotionDown();
9557 // Focused window may or may not receive ACTION_MOVE
9558 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009559 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009560 ASSERT_TRUE(moveOrCancelSequenceNum);
9561 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9562 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009563 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009564 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9565 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9566 mFocusedWindow->consumeMotionCancel();
9567 } else {
9568 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9569 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009570 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009571 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9572 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009573
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009574 mUnfocusedWindow->assertNoEvents();
9575 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009576 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009577}
9578
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009579/**
9580 * If we have no focused window, and a key comes in, we start the ANR timer.
9581 * The focused application should add a focused window before the timer runs out to prevent ANR.
9582 *
9583 * If the user touches another application during this time, the key should be dropped.
9584 * Next, if a new focused window comes in, without toggling the focused application,
9585 * then no ANR should occur.
9586 *
9587 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9588 * but in some cases the policy may not update the focused application.
9589 */
9590TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9591 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9592 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009593 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009594 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9595 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9596 mFocusedWindow->setFocusable(false);
9597
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009598 mDispatcher->onWindowInfosChanged(
9599 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009600 mFocusedWindow->consumeFocusEvent(false);
9601
9602 // Send a key. The ANR timer should start because there is no focused window.
9603 // 'focusedApplication' will get blamed if this timer completes.
9604 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009605 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009606 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9607 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009608 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009610
9611 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9612 // then the injected touches won't cause the focused event to get dropped.
9613 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9614 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9615 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9616 // For this test, it means that the key would get delivered to the window once it becomes
9617 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009618 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009619
9620 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009621 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9622 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9623 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009624
9625 // We do not consume the motion right away, because that would require dispatcher to first
9626 // process (== drop) the key event, and by that time, ANR will be raised.
9627 // Set the focused window first.
9628 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009629 mDispatcher->onWindowInfosChanged(
9630 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009631 setFocusedWindow(mFocusedWindow);
9632 mFocusedWindow->consumeFocusEvent(true);
9633 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9634 // to another application. This could be a bug / behaviour in the policy.
9635
9636 mUnfocusedWindow->consumeMotionDown();
9637
9638 ASSERT_TRUE(mDispatcher->waitForIdle());
9639 // Should not ANR because we actually have a focused window. It was just added too slowly.
9640 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9641}
9642
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009643/**
9644 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9645 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9646 * dispatcher doesn't prune pointer events incorrectly.
9647 *
9648 * This test reproduces a crash in InputDispatcher.
9649 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9650 *
9651 * Keep the currently focused application (mApplication), and have no focused window.
9652 * We set up two additional windows:
9653 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9654 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9655 * window. This window is not focusable, but is touchable.
9656 *
9657 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9658 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9659 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9660 *
9661 * Now, we touch "Another window". This window is owned by a different application than
9662 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9663 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9664 * dropping the events from its queue. Ensure that no crash occurs.
9665 *
9666 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9667 * This does not affect the test running time.
9668 */
9669TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9670 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9671 std::make_shared<FakeApplicationHandle>();
9672 systemUiApplication->setDispatchingTimeout(3000ms);
9673 mFakePolicy->setStaleEventTimeout(3000ms);
9674 sp<FakeWindowHandle> navigationBar =
9675 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9676 ADISPLAY_ID_DEFAULT);
9677 navigationBar->setFocusable(false);
9678 navigationBar->setWatchOutsideTouch(true);
9679 navigationBar->setFrame(Rect(0, 0, 100, 100));
9680
9681 mApplication->setDispatchingTimeout(3000ms);
9682 // 'mApplication' is already focused, but we call it again here to make it explicit.
9683 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9684
9685 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9686 std::make_shared<FakeApplicationHandle>();
9687 sp<FakeWindowHandle> appWindow =
9688 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9689 ADISPLAY_ID_DEFAULT);
9690 appWindow->setFocusable(false);
9691 appWindow->setFrame(Rect(100, 100, 200, 200));
9692
9693 mDispatcher->onWindowInfosChanged(
9694 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9695 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9696 mFocusedWindow->consumeFocusEvent(false);
9697
9698 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9699 // in response.
9700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9701 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9702 .build());
9703 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9704
9705 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9706 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9707 InputEventInjectionResult result =
9708 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9709 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9710 /*allowKeyRepeat=*/false);
9711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9712
9713 // Finish the gesture - lift up finger and inject ACTION_UP key event
9714 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9715 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9716 .build());
9717 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9718 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9719 /*allowKeyRepeat=*/false);
9720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9721 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9722 // getting any events yet.
9723 navigationBar->assertNoEvents();
9724
9725 // Now touch "Another window". This touch is going to a different application than the one we
9726 // are waiting for (which is 'mApplication').
9727 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9728 // trying to be injected) and to continue processing the rest of the events in the original
9729 // order.
9730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9731 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9732 .build());
9733 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9734 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9735 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9736
9737 appWindow->assertNoEvents();
9738 navigationBar->assertNoEvents();
9739}
9740
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009741// These tests ensure we cannot send touch events to a window that's positioned behind a window
9742// that has feature NO_INPUT_CHANNEL.
9743// Layout:
9744// Top (closest to user)
9745// mNoInputWindow (above all windows)
9746// mBottomWindow
9747// Bottom (furthest from user)
9748class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9749 virtual void SetUp() override {
9750 InputDispatcherTest::SetUp();
9751
9752 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009753 mNoInputWindow =
9754 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9755 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009756 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009757 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009758 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9759 // It's perfectly valid for this window to not have an associated input channel
9760
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009761 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9762 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009763 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009765 mDispatcher->onWindowInfosChanged(
9766 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009767 }
9768
9769protected:
9770 std::shared_ptr<FakeApplicationHandle> mApplication;
9771 sp<FakeWindowHandle> mNoInputWindow;
9772 sp<FakeWindowHandle> mBottomWindow;
9773};
9774
9775TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9776 PointF touchedPoint = {10, 10};
9777
Prabir Pradhan678438e2023-04-13 19:32:51 +00009778 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9779 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9780 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009781
9782 mNoInputWindow->assertNoEvents();
9783 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9784 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9785 // and therefore should prevent mBottomWindow from receiving touches
9786 mBottomWindow->assertNoEvents();
9787}
9788
9789/**
9790 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9791 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9792 */
9793TEST_F(InputDispatcherMultiWindowOcclusionTests,
9794 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009795 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9796 "Window with input channel and NO_INPUT_CHANNEL",
9797 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009798
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009799 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009800 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009801 mDispatcher->onWindowInfosChanged(
9802 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009803
9804 PointF touchedPoint = {10, 10};
9805
Prabir Pradhan678438e2023-04-13 19:32:51 +00009806 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9807 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9808 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009809
9810 mNoInputWindow->assertNoEvents();
9811 mBottomWindow->assertNoEvents();
9812}
9813
Vishnu Nair958da932020-08-21 17:12:37 -07009814class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9815protected:
9816 std::shared_ptr<FakeApplicationHandle> mApp;
9817 sp<FakeWindowHandle> mWindow;
9818 sp<FakeWindowHandle> mMirror;
9819
9820 virtual void SetUp() override {
9821 InputDispatcherTest::SetUp();
9822 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009823 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009824 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009825 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9826 mWindow->setFocusable(true);
9827 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009828 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009829 }
9830};
9831
9832TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9833 // Request focus on a mirrored window
9834 setFocusedWindow(mMirror);
9835
9836 // window gets focused
9837 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009839 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009840 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9841}
9842
9843// A focused & mirrored window remains focused only if the window and its mirror are both
9844// focusable.
9845TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9846 setFocusedWindow(mMirror);
9847
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009848 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009849 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009851 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009852 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009854 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009855 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9856
9857 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009858 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009859
9860 // window loses focus since one of the windows associated with the token in not focusable
9861 mWindow->consumeFocusEvent(false);
9862
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009863 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009864 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009865 mWindow->assertNoEvents();
9866}
9867
9868// A focused & mirrored window remains focused until the window and its mirror both become
9869// invisible.
9870TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9871 setFocusedWindow(mMirror);
9872
9873 // window gets focused
9874 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009876 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009877 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009879 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009880 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9881
9882 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009883 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009884
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009886 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009887 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009889 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009890 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9891
9892 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009893 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009894
9895 // window loses focus only after all windows associated with the token become invisible.
9896 mWindow->consumeFocusEvent(false);
9897
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009898 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009899 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009900 mWindow->assertNoEvents();
9901}
9902
9903// A focused & mirrored window remains focused until both windows are removed.
9904TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9905 setFocusedWindow(mMirror);
9906
9907 // window gets focused
9908 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009910 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009911 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009913 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009914 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9915
9916 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009917 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009918
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009920 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009921 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009923 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009924 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009925
9926 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009927 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009928 mWindow->consumeFocusEvent(false);
9929
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009930 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009931 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009932 mWindow->assertNoEvents();
9933}
9934
9935// Focus request can be pending until one window becomes visible.
9936TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9937 // Request focus on an invisible mirror.
9938 mWindow->setVisible(false);
9939 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009940 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009941 setFocusedWindow(mMirror);
9942
9943 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009945 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9946 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009947
9948 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009949 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009950
9951 // window gets focused
9952 mWindow->consumeFocusEvent(true);
9953 // window gets the pending key event
9954 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9955}
Prabir Pradhan99987712020-11-10 18:43:05 -08009956
9957class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9958protected:
9959 std::shared_ptr<FakeApplicationHandle> mApp;
9960 sp<FakeWindowHandle> mWindow;
9961 sp<FakeWindowHandle> mSecondWindow;
9962
9963 void SetUp() override {
9964 InputDispatcherTest::SetUp();
9965 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009966 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009967 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009968 mSecondWindow =
9969 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009970 mSecondWindow->setFocusable(true);
9971
9972 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009973 mDispatcher->onWindowInfosChanged(
9974 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009975
9976 setFocusedWindow(mWindow);
9977 mWindow->consumeFocusEvent(true);
9978 }
9979
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009980 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009981 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009982 }
9983
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009984 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9985 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009986 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +09009987 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009988 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009989 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009990 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009991 }
9992};
9993
9994TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9995 // Ensure that capture cannot be obtained for unfocused windows.
9996 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9997 mFakePolicy->assertSetPointerCaptureNotCalled();
9998 mSecondWindow->assertNoEvents();
9999
10000 // Ensure that capture can be enabled from the focus window.
10001 requestAndVerifyPointerCapture(mWindow, true);
10002
10003 // Ensure that capture cannot be disabled from a window that does not have capture.
10004 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
10005 mFakePolicy->assertSetPointerCaptureNotCalled();
10006
10007 // Ensure that capture can be disabled from the window with capture.
10008 requestAndVerifyPointerCapture(mWindow, false);
10009}
10010
10011TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010012 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010013
10014 setFocusedWindow(mSecondWindow);
10015
10016 // Ensure that the capture disabled event was sent first.
10017 mWindow->consumeCaptureEvent(false);
10018 mWindow->consumeFocusEvent(false);
10019 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090010020 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010021
10022 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010023 notifyPointerCaptureChanged({});
10024 notifyPointerCaptureChanged(request);
10025 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080010026 mWindow->assertNoEvents();
10027 mSecondWindow->assertNoEvents();
10028 mFakePolicy->assertSetPointerCaptureNotCalled();
10029}
10030
10031TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010032 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010033
10034 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010035 notifyPointerCaptureChanged({});
10036 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010037
10038 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090010039 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010040 mWindow->consumeCaptureEvent(false);
10041 mWindow->assertNoEvents();
10042}
10043
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010044TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
10045 requestAndVerifyPointerCapture(mWindow, true);
10046
10047 // The first window loses focus.
10048 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090010049 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010050 mWindow->consumeCaptureEvent(false);
10051
10052 // Request Pointer Capture from the second window before the notification from InputReader
10053 // arrives.
10054 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010055 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010056
10057 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010058 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010059
10060 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010061 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010062
10063 mSecondWindow->consumeFocusEvent(true);
10064 mSecondWindow->consumeCaptureEvent(true);
10065}
10066
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010067TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
10068 // App repeatedly enables and disables capture.
10069 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010070 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010071 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010072 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010073 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010074 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010075
10076 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
10077 // first request is now stale, this should do nothing.
10078 notifyPointerCaptureChanged(firstRequest);
10079 mWindow->assertNoEvents();
10080
10081 // InputReader notifies that the second request was enabled.
10082 notifyPointerCaptureChanged(secondRequest);
10083 mWindow->consumeCaptureEvent(true);
10084}
10085
Prabir Pradhan7092e262022-05-03 16:51:09 +000010086TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
10087 requestAndVerifyPointerCapture(mWindow, true);
10088
10089 // App toggles pointer capture off and on.
10090 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010091 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010092
10093 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010094 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010095
10096 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10097 // preceding "disable" request.
10098 notifyPointerCaptureChanged(enableRequest);
10099
10100 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10101 // any notifications.
10102 mWindow->assertNoEvents();
10103}
10104
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010105/**
10106 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10107 * mouse movements don't affect the previous mouse hovering state.
10108 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10109 * HOVER_MOVE events).
10110 */
10111TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10112 // Mouse hover on the window
10113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10114 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10115 .build());
10116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10117 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10118 .build());
10119
10120 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10121 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10122
10123 // Start pointer capture
10124 requestAndVerifyPointerCapture(mWindow, true);
10125
10126 // Send some relative mouse movements and receive them in the window.
10127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10128 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10129 .build());
10130 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10131 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10132
10133 // Stop pointer capture
10134 requestAndVerifyPointerCapture(mWindow, false);
10135
10136 // Continue hovering on the window
10137 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10138 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10139 .build());
10140 mWindow->consumeMotionEvent(
10141 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10142
10143 mWindow->assertNoEvents();
10144}
10145
Hiroki Sato25040232024-02-22 17:21:22 +090010146using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
10147
10148TEST_F(InputDispatcherPointerCaptureDeathTest,
10149 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
10150 testing::GTEST_FLAG(death_test_style) = "threadsafe";
10151 ScopedSilentDeath _silentDeath;
10152
10153 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
10154 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
10155
10156 // Dispatch a pointer changed event with a wrong token.
10157 request.window = mSecondWindow->getToken();
10158 ASSERT_DEATH(
10159 {
10160 notifyPointerCaptureChanged(request);
10161 mSecondWindow->consumeCaptureEvent(true);
10162 },
10163 "Unexpected requested window for Pointer Capture.");
10164}
10165
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010166class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10167protected:
10168 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010169
10170 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10171 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10172
10173 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10174 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10175
10176 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10177 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10178 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10179 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10180 MAXIMUM_OBSCURING_OPACITY);
10181
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010182 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10183 static constexpr gui::Uid APP_B_UID{10002};
10184 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010185
10186 sp<FakeWindowHandle> mTouchWindow;
10187
10188 virtual void SetUp() override {
10189 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010190 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010191 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10192 }
10193
10194 virtual void TearDown() override {
10195 InputDispatcherTest::TearDown();
10196 mTouchWindow.clear();
10197 }
10198
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010199 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010200 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010201 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010202 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010203 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010204 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010205 return window;
10206 }
10207
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010208 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010209 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10210 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010211 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010212 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010213 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010214 return window;
10215 }
10216
10217 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010218 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10219 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10220 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010221 }
10222};
10223
10224TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010225 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010226 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010227 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010228
10229 touch();
10230
10231 mTouchWindow->assertNoEvents();
10232}
10233
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010234TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010235 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10236 const sp<FakeWindowHandle>& w =
10237 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010238 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010239
10240 touch();
10241
10242 mTouchWindow->assertNoEvents();
10243}
10244
10245TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010246 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10247 const sp<FakeWindowHandle>& w =
10248 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010249 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010250
10251 touch();
10252
10253 w->assertNoEvents();
10254}
10255
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010256TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010257 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010258 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010259
10260 touch();
10261
10262 mTouchWindow->consumeAnyMotionDown();
10263}
10264
10265TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010266 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010267 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010268 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010269 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010270
10271 touch({PointF{100, 100}});
10272
10273 mTouchWindow->consumeAnyMotionDown();
10274}
10275
10276TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010277 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010278 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010279 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010280
10281 touch();
10282
10283 mTouchWindow->consumeAnyMotionDown();
10284}
10285
10286TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10287 const sp<FakeWindowHandle>& w =
10288 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010289 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010290
10291 touch();
10292
10293 mTouchWindow->consumeAnyMotionDown();
10294}
10295
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010296TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10297 const sp<FakeWindowHandle>& w =
10298 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010299 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010300
10301 touch();
10302
10303 w->assertNoEvents();
10304}
10305
10306/**
10307 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10308 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10309 * window, the occluding window will still receive ACTION_OUTSIDE event.
10310 */
10311TEST_F(InputDispatcherUntrustedTouchesTest,
10312 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10313 const sp<FakeWindowHandle>& w =
10314 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010315 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010316 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010317
10318 touch();
10319
10320 w->consumeMotionOutside();
10321}
10322
10323TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10324 const sp<FakeWindowHandle>& w =
10325 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010326 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010327 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010328
10329 touch();
10330
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010331 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010332}
10333
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010334TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010335 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010336 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10337 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010338 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010339
10340 touch();
10341
10342 mTouchWindow->consumeAnyMotionDown();
10343}
10344
10345TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10346 const sp<FakeWindowHandle>& w =
10347 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10348 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010349 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010350
10351 touch();
10352
10353 mTouchWindow->consumeAnyMotionDown();
10354}
10355
10356TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010357 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010358 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10359 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010360 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010361
10362 touch();
10363
10364 mTouchWindow->assertNoEvents();
10365}
10366
10367TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10368 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10369 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010370 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10371 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010372 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010373 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10374 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010375 mDispatcher->onWindowInfosChanged(
10376 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010377
10378 touch();
10379
10380 mTouchWindow->assertNoEvents();
10381}
10382
10383TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10384 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10385 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010386 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10387 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010388 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010389 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10390 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010391 mDispatcher->onWindowInfosChanged(
10392 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010393
10394 touch();
10395
10396 mTouchWindow->consumeAnyMotionDown();
10397}
10398
10399TEST_F(InputDispatcherUntrustedTouchesTest,
10400 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10401 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010402 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10403 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010404 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010405 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10406 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010407 mDispatcher->onWindowInfosChanged(
10408 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010409
10410 touch();
10411
10412 mTouchWindow->consumeAnyMotionDown();
10413}
10414
10415TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10416 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010417 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10418 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010419 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010420 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10421 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010422 mDispatcher->onWindowInfosChanged(
10423 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010424
10425 touch();
10426
10427 mTouchWindow->assertNoEvents();
10428}
10429
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010430TEST_F(InputDispatcherUntrustedTouchesTest,
10431 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10432 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010433 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10434 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010435 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010436 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10437 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010438 mDispatcher->onWindowInfosChanged(
10439 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010440
10441 touch();
10442
10443 mTouchWindow->assertNoEvents();
10444}
10445
10446TEST_F(InputDispatcherUntrustedTouchesTest,
10447 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10448 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010449 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10450 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010451 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010452 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10453 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010454 mDispatcher->onWindowInfosChanged(
10455 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010456
10457 touch();
10458
10459 mTouchWindow->consumeAnyMotionDown();
10460}
10461
10462TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10463 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010464 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10465 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010466 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010467
10468 touch();
10469
10470 mTouchWindow->consumeAnyMotionDown();
10471}
10472
10473TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10474 const sp<FakeWindowHandle>& w =
10475 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010476 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010477
10478 touch();
10479
10480 mTouchWindow->consumeAnyMotionDown();
10481}
10482
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010483TEST_F(InputDispatcherUntrustedTouchesTest,
10484 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10485 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10486 const sp<FakeWindowHandle>& w =
10487 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010488 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010489
10490 touch();
10491
10492 mTouchWindow->assertNoEvents();
10493}
10494
10495TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10496 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10497 const sp<FakeWindowHandle>& w =
10498 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010499 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010500
10501 touch();
10502
10503 mTouchWindow->consumeAnyMotionDown();
10504}
10505
10506TEST_F(InputDispatcherUntrustedTouchesTest,
10507 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10508 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10509 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010510 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10511 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010512 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010513
10514 touch();
10515
10516 mTouchWindow->consumeAnyMotionDown();
10517}
10518
10519TEST_F(InputDispatcherUntrustedTouchesTest,
10520 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10521 const sp<FakeWindowHandle>& w1 =
10522 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10523 OPACITY_BELOW_THRESHOLD);
10524 const sp<FakeWindowHandle>& w2 =
10525 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10526 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010527 mDispatcher->onWindowInfosChanged(
10528 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010529
10530 touch();
10531
10532 mTouchWindow->assertNoEvents();
10533}
10534
10535/**
10536 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10537 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10538 * (which alone would result in allowing touches) does not affect the blocking behavior.
10539 */
10540TEST_F(InputDispatcherUntrustedTouchesTest,
10541 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10542 const sp<FakeWindowHandle>& wB =
10543 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10544 OPACITY_BELOW_THRESHOLD);
10545 const sp<FakeWindowHandle>& wC =
10546 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10547 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010548 mDispatcher->onWindowInfosChanged(
10549 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010550
10551 touch();
10552
10553 mTouchWindow->assertNoEvents();
10554}
10555
10556/**
10557 * This test is testing that a window from a different UID but with same application token doesn't
10558 * block the touch. Apps can share the application token for close UI collaboration for example.
10559 */
10560TEST_F(InputDispatcherUntrustedTouchesTest,
10561 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10562 const sp<FakeWindowHandle>& w =
10563 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10564 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010565 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010566
10567 touch();
10568
10569 mTouchWindow->consumeAnyMotionDown();
10570}
10571
arthurhungb89ccb02020-12-30 16:19:01 +080010572class InputDispatcherDragTests : public InputDispatcherTest {
10573protected:
10574 std::shared_ptr<FakeApplicationHandle> mApp;
10575 sp<FakeWindowHandle> mWindow;
10576 sp<FakeWindowHandle> mSecondWindow;
10577 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010578 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010579 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10580 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010581
10582 void SetUp() override {
10583 InputDispatcherTest::SetUp();
10584 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010585 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010586 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010587
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010588 mSecondWindow =
10589 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010590 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010591
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010592 mSpyWindow =
10593 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010594 mSpyWindow->setSpy(true);
10595 mSpyWindow->setTrustedOverlay(true);
10596 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10597
arthurhungb89ccb02020-12-30 16:19:01 +080010598 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010599 mDispatcher->onWindowInfosChanged(
10600 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10601 {},
10602 0,
10603 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010604 }
10605
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010606 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10607 switch (fromSource) {
10608 case AINPUT_SOURCE_TOUCHSCREEN:
10609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010610 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010611 ADISPLAY_ID_DEFAULT, {50, 50}))
10612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10613 break;
10614 case AINPUT_SOURCE_STYLUS:
10615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010616 injectMotionEvent(*mDispatcher,
10617 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10618 AINPUT_SOURCE_STYLUS)
10619 .buttonState(
10620 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10621 .pointer(PointerBuilder(0, ToolType::STYLUS)
10622 .x(50)
10623 .y(50))
10624 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010625 break;
10626 case AINPUT_SOURCE_MOUSE:
10627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010628 injectMotionEvent(*mDispatcher,
10629 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10630 AINPUT_SOURCE_MOUSE)
10631 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10632 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10633 ToolType::MOUSE)
10634 .x(50)
10635 .y(50))
10636 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010637 break;
10638 default:
10639 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10640 }
arthurhungb89ccb02020-12-30 16:19:01 +080010641
10642 // Window should receive motion event.
10643 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010644 // Spy window should also receive motion event
10645 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010646 }
10647
10648 // Start performing drag, we will create a drag window and transfer touch to it.
10649 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10650 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010651 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010652 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010653 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010654 }
arthurhungb89ccb02020-12-30 16:19:01 +080010655
10656 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010657 mDragWindow =
10658 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010659 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010660 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10661 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10662 {},
10663 0,
10664 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010665
10666 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010667 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010668 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10669 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010670 if (transferred) {
10671 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010672 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010673 }
10674 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010675 }
10676};
10677
10678TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010679 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010680
10681 // Move on window.
10682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010683 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010684 ADISPLAY_ID_DEFAULT, {50, 50}))
10685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010686 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010687 mWindow->consumeDragEvent(false, 50, 50);
10688 mSecondWindow->assertNoEvents();
10689
10690 // Move to another window.
10691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010692 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010693 ADISPLAY_ID_DEFAULT, {150, 50}))
10694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010695 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010696 mWindow->consumeDragEvent(true, 150, 50);
10697 mSecondWindow->consumeDragEvent(false, 50, 50);
10698
10699 // Move back to original window.
10700 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010701 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010702 ADISPLAY_ID_DEFAULT, {50, 50}))
10703 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010704 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010705 mWindow->consumeDragEvent(false, 50, 50);
10706 mSecondWindow->consumeDragEvent(true, -50, 50);
10707
10708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010709 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10710 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010712 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010713 mWindow->assertNoEvents();
10714 mSecondWindow->assertNoEvents();
10715}
10716
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010717TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010718 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010719
10720 // No cancel event after drag start
10721 mSpyWindow->assertNoEvents();
10722
10723 const MotionEvent secondFingerDownEvent =
10724 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10725 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010726 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10727 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010728 .build();
10729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010730 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010731 InputEventInjectionSync::WAIT_FOR_RESULT))
10732 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10733
10734 // Receives cancel for first pointer after next pointer down
10735 mSpyWindow->consumeMotionCancel();
10736 mSpyWindow->consumeMotionDown();
10737
10738 mSpyWindow->assertNoEvents();
10739}
10740
arthurhungf452d0b2021-01-06 00:19:52 +080010741TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010742 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010743
10744 // Move on window.
10745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010746 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010747 ADISPLAY_ID_DEFAULT, {50, 50}))
10748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010749 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010750 mWindow->consumeDragEvent(false, 50, 50);
10751 mSecondWindow->assertNoEvents();
10752
10753 // Move to another window.
10754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010755 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010756 ADISPLAY_ID_DEFAULT, {150, 50}))
10757 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010758 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010759 mWindow->consumeDragEvent(true, 150, 50);
10760 mSecondWindow->consumeDragEvent(false, 50, 50);
10761
10762 // drop to another window.
10763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010764 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010765 {150, 50}))
10766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010767 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010768 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010769 mWindow->assertNoEvents();
10770 mSecondWindow->assertNoEvents();
10771}
10772
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010773TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10774 startDrag();
10775
10776 // No cancel event after drag start
10777 mSpyWindow->assertNoEvents();
10778
10779 const MotionEvent secondFingerDownEvent =
10780 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10781 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10782 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10783 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10784 .build();
10785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10786 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10787 InputEventInjectionSync::WAIT_FOR_RESULT))
10788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10789
10790 // Receives cancel for first pointer after next pointer down
10791 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010792 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010793 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10794
10795 mSpyWindow->assertNoEvents();
10796
10797 // Spy window calls pilfer pointers
10798 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10799 mDragWindow->assertNoEvents();
10800
10801 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010802 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010803 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10804 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10805 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10806 .build();
10807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010808 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010809 InputEventInjectionSync::WAIT_FOR_RESULT))
10810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10811
10812 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010813 mDragWindow->consumeMotionEvent(
10814 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010815 mDragWindow->assertNoEvents();
10816}
10817
arthurhung6d4bed92021-03-17 11:59:33 +080010818TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010819 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010820
10821 // Move on window and keep button pressed.
10822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010823 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010824 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10825 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010827 .build()))
10828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010829 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010830 mWindow->consumeDragEvent(false, 50, 50);
10831 mSecondWindow->assertNoEvents();
10832
10833 // Move to another window and release button, expect to drop item.
10834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010835 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010836 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10837 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010838 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010839 .build()))
10840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010841 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010842 mWindow->assertNoEvents();
10843 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010844 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010845
10846 // nothing to the window.
10847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010848 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010849 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10850 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010852 .build()))
10853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010854 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010855 mWindow->assertNoEvents();
10856 mSecondWindow->assertNoEvents();
10857}
10858
Arthur Hung54745652022-04-20 07:17:41 +000010859TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010860 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010861
10862 // Set second window invisible.
10863 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010864 mDispatcher->onWindowInfosChanged(
10865 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010866
10867 // Move on window.
10868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010870 ADISPLAY_ID_DEFAULT, {50, 50}))
10871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010872 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010873 mWindow->consumeDragEvent(false, 50, 50);
10874 mSecondWindow->assertNoEvents();
10875
10876 // Move to another window.
10877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010878 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010879 ADISPLAY_ID_DEFAULT, {150, 50}))
10880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010881 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010882 mWindow->consumeDragEvent(true, 150, 50);
10883 mSecondWindow->assertNoEvents();
10884
10885 // drop to another window.
10886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010887 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010888 {150, 50}))
10889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010890 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010891 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010892 mWindow->assertNoEvents();
10893 mSecondWindow->assertNoEvents();
10894}
10895
Arthur Hung54745652022-04-20 07:17:41 +000010896TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010897 // Ensure window could track pointerIds if it didn't support split touch.
10898 mWindow->setPreventSplitting(true);
10899
Arthur Hung54745652022-04-20 07:17:41 +000010900 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010901 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010902 {50, 50}))
10903 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10904 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10905
10906 const MotionEvent secondFingerDownEvent =
10907 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10908 .displayId(ADISPLAY_ID_DEFAULT)
10909 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010910 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10911 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010912 .build();
10913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010914 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010915 InputEventInjectionSync::WAIT_FOR_RESULT))
10916 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010917 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010918
10919 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010920 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010921}
10922
10923TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10924 // First down on second window.
10925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010926 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010927 {150, 50}))
10928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10929
10930 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10931
10932 // Second down on first window.
10933 const MotionEvent secondFingerDownEvent =
10934 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10935 .displayId(ADISPLAY_ID_DEFAULT)
10936 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010937 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10938 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010939 .build();
10940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010941 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010942 InputEventInjectionSync::WAIT_FOR_RESULT))
10943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10944 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010945 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010946
10947 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010948 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010949
10950 // Move on window.
10951 const MotionEvent secondFingerMoveEvent =
10952 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10953 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010954 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10955 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010956 .build();
10957 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010958 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010959 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010960 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010961 mWindow->consumeDragEvent(false, 50, 50);
10962 mSecondWindow->consumeMotionMove();
10963
10964 // Release the drag pointer should perform drop.
10965 const MotionEvent secondFingerUpEvent =
10966 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10967 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010968 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10969 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010970 .build();
10971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010972 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010973 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010974 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010975 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010976 mWindow->assertNoEvents();
10977 mSecondWindow->consumeMotionMove();
10978}
10979
Arthur Hung3915c1f2022-05-31 07:17:17 +000010980TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010981 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010982
10983 // Update window of second display.
10984 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010985 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010986 mDispatcher->onWindowInfosChanged(
10987 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10988 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10989 {},
10990 0,
10991 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010992
10993 // Let second display has a touch state.
10994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010995 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010996 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10997 AINPUT_SOURCE_TOUCHSCREEN)
10998 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010999 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011000 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000011001 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011002 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011003 mDispatcher->onWindowInfosChanged(
11004 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
11005 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
11006 {},
11007 0,
11008 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000011009
11010 // Move on window.
11011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011012 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011013 ADISPLAY_ID_DEFAULT, {50, 50}))
11014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011015 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011016 mWindow->consumeDragEvent(false, 50, 50);
11017 mSecondWindow->assertNoEvents();
11018
11019 // Move to another window.
11020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011021 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011022 ADISPLAY_ID_DEFAULT, {150, 50}))
11023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011024 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011025 mWindow->consumeDragEvent(true, 150, 50);
11026 mSecondWindow->consumeDragEvent(false, 50, 50);
11027
11028 // drop to another window.
11029 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011030 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011031 {150, 50}))
11032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011033 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011034 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000011035 mWindow->assertNoEvents();
11036 mSecondWindow->assertNoEvents();
11037}
11038
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011039TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
11040 startDrag(true, AINPUT_SOURCE_MOUSE);
11041 // Move on window.
11042 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011043 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011044 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
11045 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011046 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011047 .x(50)
11048 .y(50))
11049 .build()))
11050 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011051 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011052 mWindow->consumeDragEvent(false, 50, 50);
11053 mSecondWindow->assertNoEvents();
11054
11055 // Move to another window.
11056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011057 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011058 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
11059 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011060 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011061 .x(150)
11062 .y(50))
11063 .build()))
11064 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011065 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011066 mWindow->consumeDragEvent(true, 150, 50);
11067 mSecondWindow->consumeDragEvent(false, 50, 50);
11068
11069 // drop to another window.
11070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011071 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011072 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
11073 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011074 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011075 .x(150)
11076 .y(50))
11077 .build()))
11078 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000011079 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011080 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011081 mWindow->assertNoEvents();
11082 mSecondWindow->assertNoEvents();
11083}
11084
Linnan Li5af92f92023-07-14 14:36:22 +080011085/**
11086 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
11087 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
11088 */
11089TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
11090 // Down on second window
11091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11092 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11093 {150, 50}))
11094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11095
11096 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
11097 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
11098
11099 // Down on first window
11100 const MotionEvent secondFingerDownEvent =
11101 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11102 .displayId(ADISPLAY_ID_DEFAULT)
11103 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11104 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11105 .build();
11106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11107 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11108 InputEventInjectionSync::WAIT_FOR_RESULT))
11109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11110 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11111 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
11112 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
11113
11114 // Start drag on first window
11115 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11116
11117 // Trigger cancel
11118 mDispatcher->cancelCurrentTouch();
11119 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011120 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11121 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011122 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11123
11124 ASSERT_TRUE(mDispatcher->waitForIdle());
11125 // The D&D finished with nullptr
11126 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11127
11128 // Remove drag window
11129 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11130
11131 // Inject a simple gesture, ensure dispatcher not crashed
11132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11133 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11134 PointF{50, 50}))
11135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11136 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11137
11138 const MotionEvent moveEvent =
11139 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11140 .displayId(ADISPLAY_ID_DEFAULT)
11141 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11142 .build();
11143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11144 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11145 InputEventInjectionSync::WAIT_FOR_RESULT))
11146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11147 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11148
11149 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11150 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11151 {50, 50}))
11152 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11153 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11154}
11155
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011156TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11157 // Start hovering over the window.
11158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11159 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11160 ADISPLAY_ID_DEFAULT, {50, 50}));
11161
11162 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11163 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11164
11165 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11166 << "Drag and drop should not work with a hovering pointer";
11167}
11168
Vishnu Nair062a8672021-09-03 16:07:44 -070011169class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11170
11171TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11172 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->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011176 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11177 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011178 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011179 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011180 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011181
11182 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011183 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011184 window->assertNoEvents();
11185
Prabir Pradhan678438e2023-04-13 19:32:51 +000011186 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11187 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011188 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11189 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011190 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011191 window->assertNoEvents();
11192
11193 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011194 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011195 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011196
Prabir Pradhan678438e2023-04-13 19:32:51 +000011197 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011198 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11199
Prabir Pradhan678438e2023-04-13 19:32:51 +000011200 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11201 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011202 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11203 window->assertNoEvents();
11204}
11205
11206TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11207 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11208 std::make_shared<FakeApplicationHandle>();
11209 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011210 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11211 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011212 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011213 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011214 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011215 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011216 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11217 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011218 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011219 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011220 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11221 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011222 mDispatcher->onWindowInfosChanged(
11223 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011224 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011225 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011226
11227 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011228 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011229 window->assertNoEvents();
11230
Prabir Pradhan678438e2023-04-13 19:32:51 +000011231 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11232 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011233 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11234 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011235 window->assertNoEvents();
11236
11237 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011238 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011239 mDispatcher->onWindowInfosChanged(
11240 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011241
Prabir Pradhan678438e2023-04-13 19:32:51 +000011242 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011243 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11244
Prabir Pradhan678438e2023-04-13 19:32:51 +000011245 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11246 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011247 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11248 window->assertNoEvents();
11249}
11250
11251TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11252 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11253 std::make_shared<FakeApplicationHandle>();
11254 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011255 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11256 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011257 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011258 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011259 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011261 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11262 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011263 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011264 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011265 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11266 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011267 mDispatcher->onWindowInfosChanged(
11268 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011269 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011270 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011271
11272 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011273 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011274 window->assertNoEvents();
11275
Prabir Pradhan678438e2023-04-13 19:32:51 +000011276 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11277 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011278 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11279 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011280 window->assertNoEvents();
11281
11282 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011283 mDispatcher->onWindowInfosChanged(
11284 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011285
Prabir Pradhan678438e2023-04-13 19:32:51 +000011286 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011287 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11288
Prabir Pradhan678438e2023-04-13 19:32:51 +000011289 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11290 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011291 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11292 window->assertNoEvents();
11293}
11294
Antonio Kantekf16f2832021-09-28 04:39:20 +000011295class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11296protected:
11297 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011298 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011299 sp<FakeWindowHandle> mWindow;
11300 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011301 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011302
11303 void SetUp() override {
11304 InputDispatcherTest::SetUp();
11305
11306 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011307 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011308 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011309 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011310 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011311 mSecondWindow =
11312 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011313 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011314 mThirdWindow =
11315 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11316 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11317 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011318
11319 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011320 mDispatcher->onWindowInfosChanged(
11321 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11322 {},
11323 0,
11324 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011325 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011326 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011327
Antonio Kantek15beb512022-06-13 22:35:41 +000011328 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011329 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011330 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011331 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11332 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011333 mThirdWindow->assertNoEvents();
11334 }
11335
11336 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11337 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011338 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011339 SECOND_DISPLAY_ID)) {
11340 mWindow->assertNoEvents();
11341 mSecondWindow->assertNoEvents();
11342 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011343 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011344 }
11345
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011346 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011347 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011348 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11349 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011350 mWindow->consumeTouchModeEvent(inTouchMode);
11351 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011352 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011353 }
11354};
11355
Antonio Kantek26defcf2022-02-08 01:12:27 +000011356TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011357 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011358 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11359 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011360 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011361}
11362
Antonio Kantek26defcf2022-02-08 01:12:27 +000011363TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11364 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011365 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011366 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011367 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011368 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011369 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011370 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011371 mWindow->assertNoEvents();
11372 mSecondWindow->assertNoEvents();
11373}
11374
11375TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11376 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011377 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011378 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011379 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011380 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011381 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011382}
11383
Antonio Kantekf16f2832021-09-28 04:39:20 +000011384TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011385 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011386 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11387 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011388 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011389 mWindow->assertNoEvents();
11390 mSecondWindow->assertNoEvents();
11391}
11392
Antonio Kantek15beb512022-06-13 22:35:41 +000011393TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11394 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11395 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11396 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011397 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011398 mWindow->assertNoEvents();
11399 mSecondWindow->assertNoEvents();
11400 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11401}
11402
Antonio Kantek48710e42022-03-24 14:19:30 -070011403TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11404 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11406 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011407 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11408 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11409
11410 // Then remove focus.
11411 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011412 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011413
11414 // Assert that caller can switch touch mode by owning one of the last interacted window.
11415 const WindowInfo& windowInfo = *mWindow->getInfo();
11416 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11417 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011418 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011419}
11420
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011421class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11422public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011423 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011424 std::shared_ptr<FakeApplicationHandle> application =
11425 std::make_shared<FakeApplicationHandle>();
11426 std::string name = "Fake Spy ";
11427 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011428 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11429 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011430 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011431 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011432 return spy;
11433 }
11434
11435 sp<FakeWindowHandle> createForeground() {
11436 std::shared_ptr<FakeApplicationHandle> application =
11437 std::make_shared<FakeApplicationHandle>();
11438 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011439 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11440 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011441 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011442 return window;
11443 }
11444
11445private:
11446 int mSpyCount{0};
11447};
11448
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011449using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011450/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011451 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11452 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011453TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011454 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011455 ScopedSilentDeath _silentDeath;
11456
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011457 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011458 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011459 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011460 ".* not a trusted overlay");
11461}
11462
11463/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011464 * Input injection into a display with a spy window but no foreground windows should succeed.
11465 */
11466TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011467 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011468 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011469
11470 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011471 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11473 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11474}
11475
11476/**
11477 * Verify the order in which different input windows receive events. The touched foreground window
11478 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11479 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11480 * receive events before ones belows it.
11481 *
11482 * Here, we set up a scenario with four windows in the following Z order from the top:
11483 * spy1, spy2, window, spy3.
11484 * We then inject an event and verify that the foreground "window" receives it first, followed by
11485 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11486 * window.
11487 */
11488TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11489 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011490 auto spy1 = createSpy();
11491 auto spy2 = createSpy();
11492 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011493 mDispatcher->onWindowInfosChanged(
11494 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011495 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11496 const size_t numChannels = channels.size();
11497
Michael Wright8e9a8562022-02-09 13:44:29 +000011498 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011499 if (!epollFd.ok()) {
11500 FAIL() << "Failed to create epoll fd";
11501 }
11502
11503 for (size_t i = 0; i < numChannels; i++) {
11504 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11505 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11506 FAIL() << "Failed to add fd to epoll";
11507 }
11508 }
11509
11510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011511 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11513
11514 std::vector<size_t> eventOrder;
11515 std::vector<struct epoll_event> events(numChannels);
11516 for (;;) {
11517 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11518 (100ms).count());
11519 if (nFds < 0) {
11520 FAIL() << "Failed to call epoll_wait";
11521 }
11522 if (nFds == 0) {
11523 break; // epoll_wait timed out
11524 }
11525 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011526 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011527 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011528 channels[i]->consumeMotionDown();
11529 }
11530 }
11531
11532 // Verify the order in which the events were received.
11533 EXPECT_EQ(3u, eventOrder.size());
11534 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11535 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11536 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11537}
11538
11539/**
11540 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11541 */
11542TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11543 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011544 auto spy = createSpy();
11545 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011546 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011547
11548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011549 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011550 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11551 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11552 spy->assertNoEvents();
11553}
11554
11555/**
11556 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11557 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11558 * to the window.
11559 */
11560TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11561 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011562 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011563 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011564 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011565
11566 // Inject an event outside the spy window's touchable region.
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 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11570 window->consumeMotionDown();
11571 spy->assertNoEvents();
11572 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011573 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011574 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11575 window->consumeMotionUp();
11576 spy->assertNoEvents();
11577
11578 // Inject an event inside the spy window's touchable region.
11579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011580 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011581 {5, 10}))
11582 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11583 window->consumeMotionDown();
11584 spy->consumeMotionDown();
11585}
11586
11587/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011588 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011589 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011590 */
11591TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11592 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011593 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011594 auto spy = createSpy();
11595 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011596 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011597 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011598 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011599
11600 // Inject an event outside the spy window's frame and touchable region.
11601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011603 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11605 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011606 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011607}
11608
11609/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011610 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11611 * pointers that are down within its bounds.
11612 */
11613TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11614 auto windowLeft = createForeground();
11615 windowLeft->setFrame({0, 0, 100, 200});
11616 auto windowRight = createForeground();
11617 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011618 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011619 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011620 mDispatcher->onWindowInfosChanged(
11621 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011622
11623 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011624 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011625 {50, 50}))
11626 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11627 windowLeft->consumeMotionDown();
11628 spy->consumeMotionDown();
11629
11630 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011631 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011632 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011633 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11634 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011635 .build();
11636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011637 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011638 InputEventInjectionSync::WAIT_FOR_RESULT))
11639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11640 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011641 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011642}
11643
11644/**
11645 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11646 * the spy should receive the second pointer with ACTION_DOWN.
11647 */
11648TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11649 auto window = createForeground();
11650 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011651 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011652 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011653 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011654
11655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011657 {50, 50}))
11658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11659 window->consumeMotionDown();
11660 spyRight->assertNoEvents();
11661
11662 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011663 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011664 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011665 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11666 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011667 .build();
11668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011669 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011670 InputEventInjectionSync::WAIT_FOR_RESULT))
11671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011672 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011673 spyRight->consumeMotionDown();
11674}
11675
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011676/**
11677 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11678 * windows should be allowed to control split touch.
11679 */
11680TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011681 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011682 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011683 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011684 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011685
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011686 auto window = createForeground();
11687 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011688
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011689 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011690
11691 // First finger down, no window touched.
11692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011694 {100, 200}))
11695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11696 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11697 window->assertNoEvents();
11698
11699 // Second finger down on window, the window should receive touch down.
11700 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011701 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011702 .displayId(ADISPLAY_ID_DEFAULT)
11703 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011704 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11705 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011706 .build();
11707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011708 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011709 InputEventInjectionSync::WAIT_FOR_RESULT))
11710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11711
11712 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011713 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011714}
11715
11716/**
11717 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11718 * do not receive key events.
11719 */
11720TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011721 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011722 spy->setFocusable(false);
11723
11724 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011725 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011726 setFocusedWindow(window);
11727 window->consumeFocusEvent(true);
11728
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011730 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11731 window->consumeKeyDown(ADISPLAY_ID_NONE);
11732
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011734 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11735 window->consumeKeyUp(ADISPLAY_ID_NONE);
11736
11737 spy->assertNoEvents();
11738}
11739
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011740using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11741
11742/**
11743 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11744 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11745 */
11746TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11747 auto window = createForeground();
11748 auto spy1 = createSpy();
11749 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011750 mDispatcher->onWindowInfosChanged(
11751 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011752
11753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11756 window->consumeMotionDown();
11757 spy1->consumeMotionDown();
11758 spy2->consumeMotionDown();
11759
11760 // Pilfer pointers from the second spy window.
11761 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11762 spy2->assertNoEvents();
11763 spy1->consumeMotionCancel();
11764 window->consumeMotionCancel();
11765
11766 // The rest of the gesture should only be sent to the second spy window.
11767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011769 ADISPLAY_ID_DEFAULT))
11770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11771 spy2->consumeMotionMove();
11772 spy1->assertNoEvents();
11773 window->assertNoEvents();
11774}
11775
11776/**
11777 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11778 * in the middle of the gesture.
11779 */
11780TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11781 auto window = createForeground();
11782 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011783 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011784
11785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11788 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11789 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11790
11791 window->releaseChannel();
11792
11793 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11794
11795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011796 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011797 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11798 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11799}
11800
11801/**
11802 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11803 * the spy, but not to any other windows.
11804 */
11805TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11806 auto spy = createSpy();
11807 auto window = createForeground();
11808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011809 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011810
11811 // First finger down on the window and the spy.
11812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011813 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011814 {100, 200}))
11815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11816 spy->consumeMotionDown();
11817 window->consumeMotionDown();
11818
11819 // Spy window pilfers the pointers.
11820 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11821 window->consumeMotionCancel();
11822
11823 // Second finger down on the window and spy, but the window should not receive the pointer down.
11824 const MotionEvent secondFingerDownEvent =
11825 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11826 .displayId(ADISPLAY_ID_DEFAULT)
11827 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011828 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11829 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011830 .build();
11831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011832 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011833 InputEventInjectionSync::WAIT_FOR_RESULT))
11834 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11835
Harry Cutts33476232023-01-30 19:57:29 +000011836 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011837
11838 // Third finger goes down outside all windows, so injection should fail.
11839 const MotionEvent thirdFingerDownEvent =
11840 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11841 .displayId(ADISPLAY_ID_DEFAULT)
11842 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011843 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11844 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11845 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011846 .build();
11847 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011848 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011849 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011850 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011851
11852 spy->assertNoEvents();
11853 window->assertNoEvents();
11854}
11855
11856/**
11857 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11858 */
11859TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11860 auto spy = createSpy();
11861 spy->setFrame(Rect(0, 0, 100, 100));
11862 auto window = createForeground();
11863 window->setFrame(Rect(0, 0, 200, 200));
11864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011865 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011866
11867 // First finger down on the window only
11868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011869 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011870 {150, 150}))
11871 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11872 window->consumeMotionDown();
11873
11874 // Second finger down on the spy and window
11875 const MotionEvent secondFingerDownEvent =
11876 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11877 .displayId(ADISPLAY_ID_DEFAULT)
11878 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011879 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11880 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011881 .build();
11882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011883 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011884 InputEventInjectionSync::WAIT_FOR_RESULT))
11885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11886 spy->consumeMotionDown();
11887 window->consumeMotionPointerDown(1);
11888
11889 // Third finger down on the spy and window
11890 const MotionEvent thirdFingerDownEvent =
11891 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11892 .displayId(ADISPLAY_ID_DEFAULT)
11893 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011894 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11895 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11896 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011897 .build();
11898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011899 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011900 InputEventInjectionSync::WAIT_FOR_RESULT))
11901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11902 spy->consumeMotionPointerDown(1);
11903 window->consumeMotionPointerDown(2);
11904
11905 // Spy window pilfers the pointers.
11906 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011907 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11908 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011909
11910 spy->assertNoEvents();
11911 window->assertNoEvents();
11912}
11913
11914/**
11915 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11916 * other windows should be canceled. If this results in the cancellation of all pointers for some
11917 * window, then that window should receive ACTION_CANCEL.
11918 */
11919TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11920 auto spy = createSpy();
11921 spy->setFrame(Rect(0, 0, 100, 100));
11922 auto window = createForeground();
11923 window->setFrame(Rect(0, 0, 200, 200));
11924
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011925 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011926
11927 // First finger down on both spy and window
11928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011929 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011930 {10, 10}))
11931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11932 window->consumeMotionDown();
11933 spy->consumeMotionDown();
11934
11935 // Second finger down on the spy and window
11936 const MotionEvent secondFingerDownEvent =
11937 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11938 .displayId(ADISPLAY_ID_DEFAULT)
11939 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011940 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11941 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011942 .build();
11943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011944 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011945 InputEventInjectionSync::WAIT_FOR_RESULT))
11946 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11947 spy->consumeMotionPointerDown(1);
11948 window->consumeMotionPointerDown(1);
11949
11950 // Spy window pilfers the pointers.
11951 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11952 window->consumeMotionCancel();
11953
11954 spy->assertNoEvents();
11955 window->assertNoEvents();
11956}
11957
11958/**
11959 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11960 * be sent to other windows
11961 */
11962TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11963 auto spy = createSpy();
11964 spy->setFrame(Rect(0, 0, 100, 100));
11965 auto window = createForeground();
11966 window->setFrame(Rect(0, 0, 200, 200));
11967
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011968 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011969
11970 // First finger down on both window and spy
11971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011972 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011973 {10, 10}))
11974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11975 window->consumeMotionDown();
11976 spy->consumeMotionDown();
11977
11978 // Spy window pilfers the pointers.
11979 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11980 window->consumeMotionCancel();
11981
11982 // Second finger down on the window only
11983 const MotionEvent secondFingerDownEvent =
11984 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11985 .displayId(ADISPLAY_ID_DEFAULT)
11986 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011987 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11988 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011989 .build();
11990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011991 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011992 InputEventInjectionSync::WAIT_FOR_RESULT))
11993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11994 window->consumeMotionDown();
11995 window->assertNoEvents();
11996
11997 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11998 spy->consumeMotionMove();
11999 spy->assertNoEvents();
12000}
12001
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012002/**
12003 * A window on the left and a window on the right. Also, a spy window that's above all of the
12004 * windows, and spanning both left and right windows.
12005 * Send simultaneous motion streams from two different devices, one to the left window, and another
12006 * to the right window.
12007 * Pilfer from spy window.
12008 * Check that the pilfering only affects the pointers that are actually being received by the spy.
12009 */
12010TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
12011 sp<FakeWindowHandle> spy = createSpy();
12012 spy->setFrame(Rect(0, 0, 200, 200));
12013 sp<FakeWindowHandle> leftWindow = createForeground();
12014 leftWindow->setFrame(Rect(0, 0, 100, 100));
12015
12016 sp<FakeWindowHandle> rightWindow = createForeground();
12017 rightWindow->setFrame(Rect(100, 0, 200, 100));
12018
12019 constexpr int32_t stylusDeviceId = 1;
12020 constexpr int32_t touchDeviceId = 2;
12021
12022 mDispatcher->onWindowInfosChanged(
12023 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
12024
12025 // Stylus down on left window and spy
12026 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
12027 .deviceId(stylusDeviceId)
12028 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
12029 .build());
12030 leftWindow->consumeMotionEvent(
12031 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
12032 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
12033
12034 // Finger down on right window and spy - but spy already has stylus
12035 mDispatcher->notifyMotion(
12036 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12037 .deviceId(touchDeviceId)
12038 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12039 .build());
12040 rightWindow->consumeMotionEvent(
12041 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070012042 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012043
12044 // Act: pilfer from spy. Spy is currently receiving touch events.
12045 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070012046 leftWindow->consumeMotionEvent(
12047 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012048 rightWindow->consumeMotionEvent(
12049 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
12050
12051 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
12052 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12053 .deviceId(stylusDeviceId)
12054 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
12055 .build());
12056 mDispatcher->notifyMotion(
12057 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12058 .deviceId(touchDeviceId)
12059 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
12060 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070012061 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012062
12063 spy->assertNoEvents();
12064 leftWindow->assertNoEvents();
12065 rightWindow->assertNoEvents();
12066}
12067
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012068TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
12069 auto window = createForeground();
12070 auto spy = createSpy();
12071 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
12072
12073 mDispatcher->notifyMotion(
12074 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
12075 .deviceId(1)
12076 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
12077 .build());
12078 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12079 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12080
12081 // Pilfer pointers from the spy window should fail.
12082 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
12083 spy->assertNoEvents();
12084 window->assertNoEvents();
12085}
12086
Prabir Pradhand65552b2021-10-07 11:23:50 -070012087class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
12088public:
12089 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
12090 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12091 std::make_shared<FakeApplicationHandle>();
12092 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012093 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12094 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012095 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012096 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012097 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012098 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012099 overlay->setTrustedOverlay(true);
12100
12101 std::shared_ptr<FakeApplicationHandle> application =
12102 std::make_shared<FakeApplicationHandle>();
12103 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012104 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
12105 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012106 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012107 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012108
12109 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012110 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012111 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012112 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012113 return {std::move(overlay), std::move(window)};
12114 }
12115
12116 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012117 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012118 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012119 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012120 }
12121
12122 void sendStylusEvent(int32_t action) {
12123 NotifyMotionArgs motionArgs =
12124 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12125 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012126 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012127 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012128 }
12129};
12130
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012131using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12132
12133TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012134 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012135 ScopedSilentDeath _silentDeath;
12136
Prabir Pradhand65552b2021-10-07 11:23:50 -070012137 auto [overlay, window] = setupStylusOverlayScenario();
12138 overlay->setTrustedOverlay(false);
12139 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012140 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12141 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012142 ".* not a trusted overlay");
12143}
12144
12145TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12146 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012147 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012148
12149 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12150 overlay->consumeMotionDown();
12151 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12152 overlay->consumeMotionUp();
12153
12154 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12155 window->consumeMotionDown();
12156 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12157 window->consumeMotionUp();
12158
12159 overlay->assertNoEvents();
12160 window->assertNoEvents();
12161}
12162
12163TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12164 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012165 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012166 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012167
12168 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12169 overlay->consumeMotionDown();
12170 window->consumeMotionDown();
12171 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12172 overlay->consumeMotionUp();
12173 window->consumeMotionUp();
12174
12175 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12176 window->consumeMotionDown();
12177 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12178 window->consumeMotionUp();
12179
12180 overlay->assertNoEvents();
12181 window->assertNoEvents();
12182}
12183
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012184/**
12185 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12186 * The scenario is as follows:
12187 * - The stylus interceptor overlay is configured as a spy window.
12188 * - The stylus interceptor spy receives the start of a new stylus gesture.
12189 * - It pilfers pointers and then configures itself to no longer be a spy.
12190 * - The stylus interceptor continues to receive the rest of the gesture.
12191 */
12192TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12193 auto [overlay, window] = setupStylusOverlayScenario();
12194 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012195 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012196
12197 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12198 overlay->consumeMotionDown();
12199 window->consumeMotionDown();
12200
12201 // The interceptor pilfers the pointers.
12202 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12203 window->consumeMotionCancel();
12204
12205 // The interceptor configures itself so that it is no longer a spy.
12206 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012207 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012208
12209 // It continues to receive the rest of the stylus gesture.
12210 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12211 overlay->consumeMotionMove();
12212 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12213 overlay->consumeMotionUp();
12214
12215 window->assertNoEvents();
12216}
12217
Prabir Pradhan5735a322022-04-11 17:23:34 +000012218struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012219 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012220 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012221 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12222 std::unique_ptr<InputDispatcher>& mDispatcher;
12223
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012224 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012225 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12226
12227 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012228 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012229 ADISPLAY_ID_DEFAULT, {100, 200},
12230 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12231 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12232 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12233 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12234 }
12235
12236 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012237 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012238 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012239 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012240 mPolicyFlags);
12241 }
12242
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012243 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012244 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12245 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012246 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12247 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012248 window->setOwnerInfo(mPid, mUid);
12249 return window;
12250 }
12251};
12252
12253using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12254
12255TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012256 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012257 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012259
12260 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12261 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12262 window->consumeMotionDown();
12263
12264 setFocusedWindow(window);
12265 window->consumeFocusEvent(true);
12266
12267 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12268 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12269 window->consumeKeyDown(ADISPLAY_ID_NONE);
12270}
12271
12272TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012273 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012274 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012276
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012277 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012278 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12279 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12280
12281 setFocusedWindow(window);
12282 window->consumeFocusEvent(true);
12283
12284 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12285 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12286 window->assertNoEvents();
12287}
12288
12289TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012290 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012291 auto window = owner.createWindow("Owned window");
12292 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012293 spy->setSpy(true);
12294 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012295 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012296
12297 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12298 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12299 spy->consumeMotionDown();
12300 window->consumeMotionDown();
12301}
12302
12303TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012304 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012305 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012306
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012307 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012308 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012309 randosSpy->setSpy(true);
12310 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012311 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012312
12313 // The event is targeted at owner's window, so injection should succeed, but the spy should
12314 // not receive the event.
12315 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12316 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12317 randosSpy->assertNoEvents();
12318 window->consumeMotionDown();
12319}
12320
12321TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012322 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012323 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012324
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012325 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012326 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012327 randosSpy->setSpy(true);
12328 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012329 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012330
12331 // A user that has injection permission can inject into any window.
12332 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012333 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012334 ADISPLAY_ID_DEFAULT));
12335 randosSpy->consumeMotionDown();
12336 window->consumeMotionDown();
12337
12338 setFocusedWindow(randosSpy);
12339 randosSpy->consumeFocusEvent(true);
12340
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012341 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012342 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12343 window->assertNoEvents();
12344}
12345
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012346TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012347 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012348 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012349
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012350 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012351 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012352 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12353 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012354 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012355
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012356 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012357 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12358 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12359 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012360 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012361}
12362
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012363using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12364
12365TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12366 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12367
12368 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12369 ADISPLAY_ID_DEFAULT);
12370 left->setFrame(Rect(0, 0, 100, 100));
12371 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12372 "Right Window", ADISPLAY_ID_DEFAULT);
12373 right->setFrame(Rect(100, 0, 200, 100));
12374 sp<FakeWindowHandle> spy =
12375 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12376 spy->setFrame(Rect(0, 0, 200, 100));
12377 spy->setTrustedOverlay(true);
12378 spy->setSpy(true);
12379
12380 mDispatcher->onWindowInfosChanged(
12381 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12382
12383 // Hover into the left window.
12384 mDispatcher->notifyMotion(
12385 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12386 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12387 .build());
12388
12389 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12390 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12391
12392 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12393 /*pointerId=*/0));
12394 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12395 /*pointerId=*/0));
12396 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12397 /*pointerId=*/0));
12398
12399 // Hover move to the right window.
12400 mDispatcher->notifyMotion(
12401 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12402 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12403 .build());
12404
12405 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12406 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12407 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12408
12409 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12410 /*pointerId=*/0));
12411 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12412 /*pointerId=*/0));
12413 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12414 /*pointerId=*/0));
12415
12416 // Stop hovering.
12417 mDispatcher->notifyMotion(
12418 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12419 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12420 .build());
12421
12422 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12423 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12424
12425 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12426 /*pointerId=*/0));
12427 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12428 /*pointerId=*/0));
12429 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12430 /*pointerId=*/0));
12431}
12432
12433TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12435
12436 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12437 ADISPLAY_ID_DEFAULT);
12438 left->setFrame(Rect(0, 0, 100, 100));
12439 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12440 "Right Window", ADISPLAY_ID_DEFAULT);
12441 right->setFrame(Rect(100, 0, 200, 100));
12442 sp<FakeWindowHandle> spy =
12443 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12444 spy->setFrame(Rect(0, 0, 200, 100));
12445 spy->setTrustedOverlay(true);
12446 spy->setSpy(true);
12447
12448 mDispatcher->onWindowInfosChanged(
12449 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12450
12451 // First pointer down on left window.
12452 mDispatcher->notifyMotion(
12453 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12454 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12455 .build());
12456
12457 left->consumeMotionDown();
12458 spy->consumeMotionDown();
12459
12460 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12461 /*pointerId=*/0));
12462 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12463 /*pointerId=*/0));
12464 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12465 /*pointerId=*/0));
12466
12467 // Second pointer down on right window.
12468 mDispatcher->notifyMotion(
12469 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12470 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12471 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12472 .build());
12473
12474 left->consumeMotionMove();
12475 right->consumeMotionDown();
12476 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12477
12478 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12479 /*pointerId=*/0));
12480 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12481 /*pointerId=*/0));
12482 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12483 /*pointerId=*/0));
12484 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12485 /*pointerId=*/1));
12486 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12487 /*pointerId=*/1));
12488 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12489 /*pointerId=*/1));
12490
12491 // Second pointer up.
12492 mDispatcher->notifyMotion(
12493 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12494 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12495 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12496 .build());
12497
12498 left->consumeMotionMove();
12499 right->consumeMotionUp();
12500 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12501
12502 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12503 /*pointerId=*/0));
12504 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12505 /*pointerId=*/0));
12506 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12507 /*pointerId=*/0));
12508 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12509 /*pointerId=*/1));
12510 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12511 /*pointerId=*/1));
12512 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12513 /*pointerId=*/1));
12514
12515 // First pointer up.
12516 mDispatcher->notifyMotion(
12517 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12518 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12519 .build());
12520
12521 left->consumeMotionUp();
12522 spy->consumeMotionUp();
12523
12524 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12525 /*pointerId=*/0));
12526 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12527 /*pointerId=*/0));
12528 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12529 /*pointerId=*/0));
12530}
12531
12532TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12534
12535 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12536 ADISPLAY_ID_DEFAULT);
12537 left->setFrame(Rect(0, 0, 100, 100));
12538 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12539 "Right Window", ADISPLAY_ID_DEFAULT);
12540 right->setFrame(Rect(100, 0, 200, 100));
12541
12542 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12543
12544 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12545 /*pointerId=*/0));
12546 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12547 /*pointerId=*/0));
12548
12549 // Hover move into the window.
12550 mDispatcher->notifyMotion(
12551 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12552 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12553 .rawXCursorPosition(50)
12554 .rawYCursorPosition(50)
12555 .deviceId(DEVICE_ID)
12556 .build());
12557
12558 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12559
12560 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12561 /*pointerId=*/0));
12562
12563 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12564 mDispatcher->notifyMotion(
12565 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12566 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12567 .rawXCursorPosition(51)
12568 .rawYCursorPosition(50)
12569 .deviceId(SECOND_DEVICE_ID)
12570 .build());
12571
12572 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12573 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12574
12575 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12576 // a HOVER_EXIT from the first device.
12577 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12578 /*pointerId=*/0));
12579 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12580 SECOND_DEVICE_ID,
12581 /*pointerId=*/0));
12582
12583 // Move the mouse outside the window. Document the current behavior, where the window does not
12584 // receive HOVER_EXIT even though the mouse left the window.
12585 mDispatcher->notifyMotion(
12586 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12587 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12588 .rawXCursorPosition(150)
12589 .rawYCursorPosition(50)
12590 .deviceId(SECOND_DEVICE_ID)
12591 .build());
12592
12593 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12594 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12595 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12596 /*pointerId=*/0));
12597 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12598 SECOND_DEVICE_ID,
12599 /*pointerId=*/0));
12600}
12601
Garfield Tane84e6f92019-08-29 17:28:41 -070012602} // namespace android::inputdispatcher