blob: 423975f75bf894246dafcf27fdab914f10e647ca [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
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000312 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800313 std::unique_lock lock(mLock);
314 base::ScopedLockAssertion assumeLocked(mLock);
315
316 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
317 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000318 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800319 enabled;
320 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000321 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
322 << ") to be called.";
323 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800324 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000325 auto request = *mPointerCaptureRequest;
326 mPointerCaptureRequest.reset();
327 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800328 }
329
330 void assertSetPointerCaptureNotCalled() {
331 std::unique_lock lock(mLock);
332 base::ScopedLockAssertion assumeLocked(mLock);
333
334 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000335 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800336 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000337 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800338 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000339 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800340 }
341
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700342 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
343 const sp<IBinder>& targetToken) {
344 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800345 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800346 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800347 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800348 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800349 }
350
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800351 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
352 std::unique_lock lock(mLock);
353 base::ScopedLockAssertion assumeLocked(mLock);
354 std::optional<sp<IBinder>> receivedToken =
355 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
356 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000357 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800358 ASSERT_EQ(token, *receivedToken);
359 }
360
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800361 /**
362 * Set policy timeout. A value of zero means next key will not be intercepted.
363 */
364 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
365 mInterceptKeyTimeout = timeout;
366 }
367
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800368 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
369
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700370 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
371
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800372 void assertUserActivityNotPoked() {
373 std::unique_lock lock(mLock);
374 base::ScopedLockAssertion assumeLocked(mLock);
375
376 std::optional<UserActivityPokeEvent> pokeEvent =
377 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
378 mNotifyUserActivity);
379
380 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000381 }
382
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800383 /**
384 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
385 * cleared after this call.
386 *
387 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
388 * earliest recorded poke event.
389 */
390 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
391 std::unique_lock lock(mLock);
392 base::ScopedLockAssertion assumeLocked(mLock);
393
394 std::optional<UserActivityPokeEvent> pokeEvent =
395 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
396 mNotifyUserActivity);
397 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
398
399 if (expectedPokeEvent) {
400 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
401 }
Josep del Riob3981622023-04-18 15:49:45 +0000402 }
403
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000404 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000405 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
406 }
407
408 void assertNotifyDeviceInteractionWasNotCalled() {
409 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
410 }
411
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000412 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
413 std::scoped_lock lock(mLock);
414 mUnhandledKeyHandler = handler;
415 }
416
417 void assertUnhandledKeyReported(int32_t keycode) {
418 std::unique_lock lock(mLock);
419 base::ScopedLockAssertion assumeLocked(mLock);
420 std::optional<int32_t> unhandledKeycode =
421 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
422 mNotifyUnhandledKey);
423 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
424 ASSERT_EQ(unhandledKeycode, keycode);
425 }
426
427 void assertUnhandledKeyNotReported() {
428 std::unique_lock lock(mLock);
429 base::ScopedLockAssertion assumeLocked(mLock);
430 std::optional<int32_t> unhandledKeycode =
431 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
432 mNotifyUnhandledKey);
433 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
434 }
435
Michael Wrightd02c5b62014-02-10 15:10:22 -0800436private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700437 std::mutex mLock;
438 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
439 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
440 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
441 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800442
Prabir Pradhan99987712020-11-10 18:43:05 -0800443 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000444
445 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800446
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700447 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700448 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800449 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
450 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700451 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800452 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
453 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700454
arthurhungf452d0b2021-01-06 00:19:52 +0800455 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800456 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800457
458 std::condition_variable mNotifyUserActivity;
459 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800460
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800461 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
462
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700463 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
464
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000465 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000466
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000467 std::condition_variable mNotifyUnhandledKey;
468 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
469 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
470
Prabir Pradhanedd96402022-02-15 01:46:16 -0800471 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
472 // for a specific container to become non-empty. When the container is non-empty, return the
473 // first entry from the container and erase it.
474 template <class T>
475 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
476 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
477 // If there is an ANR, Dispatcher won't be idle because there are still events
478 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
479 // before checking if ANR was called.
480 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
481 // to provide it some time to act. 100ms seems reasonable.
482 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
483 const std::chrono::time_point start = std::chrono::steady_clock::now();
484 std::optional<T> token =
485 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
486 if (!token.has_value()) {
487 ADD_FAILURE() << "Did not receive the ANR callback";
488 return {};
489 }
490
491 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
492 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
493 // the dispatcher started counting before this function was called
494 if (std::chrono::abs(timeout - waited) > 100ms) {
495 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
496 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
497 << "ms, but waited "
498 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
499 << "ms instead";
500 }
501 return *token;
502 }
503
504 template <class T>
505 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
506 std::queue<T>& storage,
507 std::unique_lock<std::mutex>& lock,
508 std::condition_variable& condition)
509 REQUIRES(mLock) {
510 condition.wait_for(lock, timeout,
511 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
512 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800513 return std::nullopt;
514 }
515 T item = storage.front();
516 storage.pop();
517 return std::make_optional(item);
518 }
519
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600520 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700521 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800522 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800523 }
524
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000525 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800526 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700527 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000528 mAnrWindows.push({connectionToken, pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700529 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500530 }
531
Prabir Pradhanedd96402022-02-15 01:46:16 -0800532 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000533 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500534 std::scoped_lock lock(mLock);
Prabir Pradhanfc364722024-02-08 17:51:20 +0000535 mResponsiveWindows.push({connectionToken, pid});
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500536 mNotifyAnr.notify_all();
537 }
538
539 void notifyNoFocusedWindowAnr(
540 const std::shared_ptr<InputApplicationHandle>& applicationHandle) override {
541 std::scoped_lock lock(mLock);
542 mAnrApplications.push(applicationHandle);
543 mNotifyAnr.notify_all();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800544 }
545
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800546 void notifyInputChannelBroken(const sp<IBinder>& connectionToken) override {
547 std::scoped_lock lock(mLock);
548 mBrokenInputChannels.push(connectionToken);
549 mNotifyInputChannelBroken.notify_all();
550 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800551
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600552 void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
Robert Carr740167f2018-10-11 19:03:41 -0700553
Chris Yef59a2f42020-10-16 12:55:26 -0700554 void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
555 InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
556 const std::vector<float>& values) override {}
557
558 void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
559 InputDeviceSensorAccuracy accuracy) override {}
Bernardo Rufino2e1f6512020-10-08 13:42:07 +0000560
Chris Yefb552902021-02-03 17:18:37 -0800561 void notifyVibratorState(int32_t deviceId, bool isOn) override {}
562
Prabir Pradhana41d2442023-04-20 21:30:40 +0000563 bool filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700564 std::scoped_lock lock(mLock);
Prabir Pradhana41d2442023-04-20 21:30:40 +0000565 switch (inputEvent.getType()) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700566 case InputEventType::KEY: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000567 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(inputEvent);
568 mFilteredEvent = std::make_unique<KeyEvent>(keyEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800569 break;
570 }
571
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700572 case InputEventType::MOTION: {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000573 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(inputEvent);
574 mFilteredEvent = std::make_unique<MotionEvent>(motionEvent);
Jackal Guof9696682018-10-05 12:23:23 +0800575 break;
576 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700577 default: {
578 ADD_FAILURE() << "Should only filter keys or motions";
579 break;
580 }
Jackal Guof9696682018-10-05 12:23:23 +0800581 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800582 return true;
583 }
584
Prabir Pradhana41d2442023-04-20 21:30:40 +0000585 void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override {
586 if (inputEvent.getAction() == AKEY_EVENT_ACTION_UP) {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800587 // Clear intercept state when we handled the event.
588 mInterceptKeyTimeout = 0ms;
589 }
590 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800591
Yeabkal Wubshit88a90412023-12-21 18:23:04 -0800592 void interceptMotionBeforeQueueing(int32_t, uint32_t, int32_t, nsecs_t, uint32_t&) override {}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800593
Prabir Pradhana41d2442023-04-20 21:30:40 +0000594 nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override {
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800595 nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
596 // Clear intercept state so we could dispatch the event in next wake.
597 mInterceptKeyTimeout = 0ms;
598 return delay;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800599 }
600
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000601 std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
Prabir Pradhana41d2442023-04-20 21:30:40 +0000602 uint32_t) override {
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000603 std::scoped_lock lock(mLock);
604 mReportedUnhandledKeycodes.emplace(event.getKeyCode());
605 mNotifyUnhandledKey.notify_all();
606 return mUnhandledKeyHandler != nullptr ? mUnhandledKeyHandler(event) : std::nullopt;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800607 }
608
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600609 void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
610 uint32_t policyFlags) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700611 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800612 /** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
613 * essentially a passthrough for notifySwitch.
614 */
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000615 mLastNotifySwitch =
616 NotifySwitchArgs(InputEvent::nextId(), when, policyFlags, switchValues, switchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800617 }
618
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800619 void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override {
Josep del Riob3981622023-04-18 15:49:45 +0000620 std::scoped_lock lock(mLock);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800621 mNotifyUserActivity.notify_all();
622 mUserActivityPokeEvents.push({eventTime, eventType, displayId});
Josep del Riob3981622023-04-18 15:49:45 +0000623 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800624
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700625 bool isStaleEvent(nsecs_t currentTime, nsecs_t eventTime) override {
626 return std::chrono::nanoseconds(currentTime - eventTime) >= mStaleEventTimeout;
627 }
628
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600629 void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700630 std::scoped_lock lock(mLock);
chaviwfd6d3512019-03-25 13:23:49 -0700631 mOnPointerDownToken = newToken;
632 }
633
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000634 void setPointerCapture(const PointerCaptureRequest& request) override {
Prabir Pradhan99987712020-11-10 18:43:05 -0800635 std::scoped_lock lock(mLock);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000636 mPointerCaptureRequest = {request};
Prabir Pradhan99987712020-11-10 18:43:05 -0800637 mPointerCaptureChangedCondition.notify_all();
638 }
639
arthurhungf452d0b2021-01-06 00:19:52 +0800640 void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
641 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800642 mNotifyDropWindowWasCalled = true;
arthurhungf452d0b2021-01-06 00:19:52 +0800643 mDropTargetWindowToken = token;
644 }
645
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000646 void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000647 const std::set<gui::Uid>& uids) override {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000648 ASSERT_TRUE(mNotifiedInteractions.emplace(deviceId, uids));
649 }
650
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700651 void assertFilterInputEventWasCalledInternal(
652 const std::function<void(const InputEvent&)>& verify) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700653 std::scoped_lock lock(mLock);
Siarhei Vishniakoud99e1b62019-11-26 11:01:06 -0800654 ASSERT_NE(nullptr, mFilteredEvent) << "Expected filterInputEvent() to have been called.";
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700655 verify(*mFilteredEvent);
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800656 mFilteredEvent = nullptr;
Jackal Guof9696682018-10-05 12:23:23 +0800657 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800658};
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700659} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800660
Michael Wrightd02c5b62014-02-10 15:10:22 -0800661// --- InputDispatcherTest ---
662
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000663// The trace is a global variable for now, to avoid having to pass it into all of the
664// FakeWindowHandles created throughout the tests.
665// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
666static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
667
Michael Wrightd02c5b62014-02-10 15:10:22 -0800668class InputDispatcherTest : public testing::Test {
669protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000670 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700671 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800672
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000673 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000674 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000675 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000676 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
677 std::make_unique<FakeInputTracingBackend>(
678 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700679
Harry Cutts101ee9b2023-07-06 18:04:14 +0000680 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000681 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700682 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800683 }
684
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000685 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000686 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700687 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000688 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700689 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800690 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700691
692 /**
693 * Used for debugging when writing the test
694 */
695 void dumpDispatcherState() {
696 std::string dump;
697 mDispatcher->dump(dump);
698 std::stringstream ss(dump);
699 std::string to;
700
701 while (std::getline(ss, to, '\n')) {
702 ALOGE("%s", to.c_str());
703 }
704 }
Vishnu Nair958da932020-08-21 17:12:37 -0700705
Chavi Weingarten847e8512023-03-29 00:26:09 +0000706 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700707 FocusRequest request;
708 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000709 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700710 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
711 request.displayId = window->getInfo()->displayId;
712 mDispatcher->setFocusedWindow(request);
713 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800714};
715
Michael Wrightd02c5b62014-02-10 15:10:22 -0800716TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
717 KeyEvent event;
718
719 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800720 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
721 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000722 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600723 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800724 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000725 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000726 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800727 << "Should reject key events with undefined action.";
728
729 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800730 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
731 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600732 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800733 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000734 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000735 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800736 << "Should reject key events with ACTION_MULTIPLE.";
737}
738
739TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
740 MotionEvent event;
741 PointerProperties pointerProperties[MAX_POINTERS + 1];
742 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800743 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800744 pointerProperties[i].clear();
745 pointerProperties[i].id = i;
746 pointerCoords[i].clear();
747 }
748
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800749 // Some constants commonly used below
750 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
751 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
752 constexpr int32_t metaState = AMETA_NONE;
753 constexpr MotionClassification classification = MotionClassification::NONE;
754
chaviw9eaa22c2020-07-01 16:21:27 -0700755 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800756 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800757 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000758 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700759 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700760 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
761 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000762 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800763 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000764 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000765 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800766 << "Should reject motion events with undefined action.";
767
768 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800769 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800770 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
771 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
772 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
773 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000774 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800775 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000776 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000777 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800778 << "Should reject motion events with pointer down index too large.";
779
Garfield Tanfbe732e2020-01-24 11:26:14 -0800780 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700781 AMOTION_EVENT_ACTION_POINTER_DOWN |
782 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700783 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
784 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700785 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000786 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800787 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000788 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000789 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800790 << "Should reject motion events with pointer down index too small.";
791
792 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800793 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800794 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
795 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
796 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
797 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000798 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800799 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000800 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000801 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800802 << "Should reject motion events with pointer up index too large.";
803
Garfield Tanfbe732e2020-01-24 11:26:14 -0800804 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700805 AMOTION_EVENT_ACTION_POINTER_UP |
806 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700807 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
808 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700809 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000810 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800811 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000812 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000813 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800814 << "Should reject motion events with pointer up index too small.";
815
816 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800817 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
818 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700819 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700820 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
821 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000822 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800823 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000824 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000825 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800826 << "Should reject motion events with 0 pointers.";
827
Garfield Tanfbe732e2020-01-24 11:26:14 -0800828 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
829 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700830 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700831 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
832 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000833 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800834 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000835 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000836 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800837 << "Should reject motion events with more than MAX_POINTERS pointers.";
838
839 // Rejects motion events with invalid pointer ids.
840 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800841 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
842 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700843 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700844 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
845 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000846 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800847 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000848 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000849 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800850 << "Should reject motion events with pointer ids less than 0.";
851
852 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800853 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
854 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700855 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700856 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
857 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000858 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800859 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000860 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000861 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800862 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
863
864 // Rejects motion events with duplicate pointer ids.
865 pointerProperties[0].id = 1;
866 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800867 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
868 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700869 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700870 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
871 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000872 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800873 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000874 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000875 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800876 << "Should reject motion events with duplicate pointer ids.";
877}
878
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800879/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
880
881TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
882 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000883 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800884 ASSERT_TRUE(mDispatcher->waitForIdle());
885
886 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
887}
888
889TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000890 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
891 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000892 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000893 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800894
895 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
896 args.policyFlags |= POLICY_FLAG_TRUSTED;
897 mFakePolicy->assertNotifySwitchWasCalled(args);
898}
899
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700900namespace {
901
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700902static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700903// Default input dispatching timeout if there is no focused application or paused window
904// from which to determine an appropriate dispatching timeout.
905static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
906 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
907 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800908
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800909class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800910public:
Garfield Tan15601662020-09-22 15:32:38 -0700911 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700912 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800913
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800914 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
915 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700916 if (!consumeSeq) {
917 return nullptr;
918 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000919 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800920 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700921 }
922
923 /**
924 * Receive an event without acknowledging it.
925 * Return the sequence number that could later be used to send finished signal.
926 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800927 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
928 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800929 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800930 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800931
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 std::chrono::time_point start = std::chrono::steady_clock::now();
933 status_t status = WOULD_BLOCK;
934 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800935 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700936 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800937 &rawEventPtr);
938 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700940 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800941 break;
942 }
943 }
944
945 if (status == WOULD_BLOCK) {
946 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800947 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800948 }
949
950 if (status != OK) {
951 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800952 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800953 }
954 if (event == nullptr) {
955 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800956 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800957 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700958 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800959
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700960 /**
961 * To be used together with "receiveEvent" to complete the consumption of an event.
962 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000963 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700964 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700965 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800966 }
967
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000968 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700969 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000970 ASSERT_EQ(OK, status);
971 }
972
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700973 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000974 std::optional<int32_t> expectedDisplayId,
975 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800976 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800977
978 ASSERT_NE(nullptr, event) << mName.c_str()
979 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800980 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700981 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
982 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800983
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000984 if (expectedDisplayId.has_value()) {
985 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
986 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800987
Tiger Huang8664f8c2018-10-11 19:14:35 +0800988 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700989 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800990 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700991 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000992 if (expectedFlags.has_value()) {
993 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
994 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800995 break;
996 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700997 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800998 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700999 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001000 if (expectedFlags.has_value()) {
1001 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
1002 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001003 break;
1004 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001005 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001006 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
1007 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001008 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001009 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1010 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001011 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001012 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1013 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001014 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001015 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1016 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001017 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001018 }
1019
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001020 std::unique_ptr<MotionEvent> consumeMotion() {
1021 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001022
1023 if (event == nullptr) {
1024 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1025 return nullptr;
1026 }
1027
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001028 if (event->getType() != InputEventType::MOTION) {
1029 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001030 return nullptr;
1031 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001032 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001033 }
1034
1035 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001036 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001037 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1038 ASSERT_THAT(*motionEvent, matcher);
1039 }
1040
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001041 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001042 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001043 ASSERT_NE(nullptr, event) << mName.c_str()
1044 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001045 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1046 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001047
1048 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1049 << mName.c_str() << ": event displayId should always be NONE.";
1050
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001051 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1052 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001053 }
1054
Prabir Pradhan99987712020-11-10 18:43:05 -08001055 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001056 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001057 ASSERT_NE(nullptr, event) << mName.c_str()
1058 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001059 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1060 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001061
1062 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1063 << mName.c_str() << ": event displayId should always be NONE.";
1064
1065 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1066 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1067 }
1068
arthurhungb89ccb02020-12-30 16:19:01 +08001069 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001070 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001071 ASSERT_NE(nullptr, event) << mName.c_str()
1072 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001073 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001074
1075 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1076 << mName.c_str() << ": event displayId should always be NONE.";
1077
1078 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1079 EXPECT_EQ(isExiting, dragEvent.isExiting());
1080 EXPECT_EQ(x, dragEvent.getX());
1081 EXPECT_EQ(y, dragEvent.getY());
1082 }
1083
Antonio Kantekf16f2832021-09-28 04:39:20 +00001084 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001085 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001086 ASSERT_NE(nullptr, event) << mName.c_str()
1087 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001088 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1089 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001090
1091 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1092 << mName.c_str() << ": event displayId should always be NONE.";
1093 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1094 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1095 }
1096
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001097 void assertNoEvents(std::chrono::milliseconds timeout) {
1098 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001099 if (event == nullptr) {
1100 return;
1101 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001102 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001103 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001104 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001105 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001106 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001107 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001108 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001109 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1110 ADD_FAILURE() << "Received focus event, hasFocus = "
1111 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001112 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001113 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1114 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1115 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001116 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001117 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1118 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1119 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001120 }
1121 FAIL() << mName.c_str()
1122 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001123 }
1124
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001125 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001126
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001127 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001128
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001129private:
1130 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001131 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001132
1133 std::string mName;
1134};
1135
chaviw3277faf2021-05-19 16:45:23 -05001136class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001137public:
1138 static const int32_t WIDTH = 600;
1139 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001140
Chris Yea209fde2020-07-22 13:54:51 -07001141 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001142 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001143 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001144 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001145 sp<IBinder> token;
1146 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001147 base::Result<std::unique_ptr<InputChannel>> channel =
1148 dispatcher->createInputChannel(name);
1149 token = (*channel)->getConnectionToken();
1150 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001151 }
1152
1153 inputApplicationHandle->updateInfo();
1154 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1155
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001156 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001157 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001158 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001159 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001160 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001161 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001162 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001163 mInfo.globalScaleFactor = 1.0;
1164 mInfo.touchableRegion.clear();
1165 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001166 mInfo.ownerPid = WINDOW_PID;
1167 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001168 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001169 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001170 }
1171
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001172 sp<FakeWindowHandle> clone(int32_t displayId) {
1173 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1174 handle->mInfo = mInfo;
1175 handle->mInfo.displayId = displayId;
1176 handle->mInfo.id = sId++;
1177 handle->mInputReceiver = mInputReceiver;
1178 return handle;
1179 }
1180
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001181 void setTouchable(bool touchable) {
1182 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1183 }
chaviwd1c23182019-12-20 18:44:56 -08001184
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001185 void setFocusable(bool focusable) {
1186 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1187 }
1188
1189 void setVisible(bool visible) {
1190 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1191 }
Vishnu Nair958da932020-08-21 17:12:37 -07001192
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001193 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001194 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001195 }
1196
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001197 void setPaused(bool paused) {
1198 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1199 }
1200
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001201 void setPreventSplitting(bool preventSplitting) {
1202 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001203 }
1204
1205 void setSlippery(bool slippery) {
1206 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1207 }
1208
1209 void setWatchOutsideTouch(bool watchOutside) {
1210 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1211 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001212
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001213 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1214
1215 void setInterceptsStylus(bool interceptsStylus) {
1216 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1217 }
1218
1219 void setDropInput(bool dropInput) {
1220 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1221 }
1222
1223 void setDropInputIfObscured(bool dropInputIfObscured) {
1224 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1225 }
1226
1227 void setNoInputChannel(bool noInputChannel) {
1228 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1229 }
1230
Josep del Riob3981622023-04-18 15:49:45 +00001231 void setDisableUserActivity(bool disableUserActivity) {
1232 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1233 }
1234
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001235 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1236 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1237 shouldGlobalStylusBlockTouch);
1238 }
1239
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001240 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1241
chaviw3277faf2021-05-19 16:45:23 -05001242 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001243
Bernardo Rufino7393d172021-02-26 13:56:11 +00001244 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1245
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001246 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001247 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001248 mInfo.touchableRegion.clear();
1249 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001250
1251 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1252 ui::Transform translate;
1253 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1254 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001255 }
1256
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001257 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1258
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001259 void setIsWallpaper(bool isWallpaper) {
1260 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1261 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001262
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001263 void setDupTouchToWallpaper(bool hasWallpaper) {
1264 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1265 }
chaviwd1c23182019-12-20 18:44:56 -08001266
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001267 void setTrustedOverlay(bool trustedOverlay) {
1268 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1269 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001270
chaviw9eaa22c2020-07-01 16:21:27 -07001271 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1272 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1273 }
1274
1275 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001276
yunho.shinf4a80b82020-11-16 21:13:57 +09001277 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1278
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001279 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1280 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1281 if (event == nullptr) {
1282 ADD_FAILURE() << "No event";
1283 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001284 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001285 if (event->getType() != InputEventType::KEY) {
1286 ADD_FAILURE() << "Instead of key event, got " << event;
1287 return nullptr;
1288 }
1289 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001290 }
1291
1292 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001293 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1294 ASSERT_NE(nullptr, keyEvent);
1295 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001296 }
1297
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001298 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001299 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1300 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001301 }
1302
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001303 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001304 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1305 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001306 }
1307
Svet Ganov5d3bc372020-01-26 23:11:07 -08001308 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001309 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001310 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1311 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001312 }
1313
1314 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001315 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001316 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1317 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001318 }
1319
1320 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001321 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001322 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1323 }
1324
1325 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1326 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001327 consumeMotionEvent(
1328 AllOf(WithMotionAction(ACTION_DOWN),
1329 testing::Conditional(expectedDisplayId.has_value(),
1330 WithDisplayId(*expectedDisplayId), testing::_),
1331 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1332 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001333 }
1334
Svet Ganov5d3bc372020-01-26 23:11:07 -08001335 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001336 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1337 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001338 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001339 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001340 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1341 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001342 }
1343
1344 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001345 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001346 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001347 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001348 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1349 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001350 }
1351
1352 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001353 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001354 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1355 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001356 }
1357
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001358 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1359 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001360 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1361 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001362 }
1363
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001364 void consumeMotionOutsideWithZeroedCoords() {
1365 consumeMotionEvent(
1366 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001367 }
1368
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001369 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1370 ASSERT_NE(mInputReceiver, nullptr)
1371 << "Cannot consume events from a window with no receiver";
1372 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1373 }
1374
Prabir Pradhan99987712020-11-10 18:43:05 -08001375 void consumeCaptureEvent(bool hasCapture) {
1376 ASSERT_NE(mInputReceiver, nullptr)
1377 << "Cannot consume events from a window with no receiver";
1378 mInputReceiver->consumeCaptureEvent(hasCapture);
1379 }
1380
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001381 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001382 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001383 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1384 if (event == nullptr) {
1385 ADD_FAILURE() << "No event";
1386 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001387 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001388 if (event->getType() != InputEventType::MOTION) {
1389 ADD_FAILURE() << "Instead of motion event, got " << *event;
1390 return nullptr;
1391 }
1392 std::unique_ptr<MotionEvent> motionEvent =
1393 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1394 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001395 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001396 }
1397
arthurhungb89ccb02020-12-30 16:19:01 +08001398 void consumeDragEvent(bool isExiting, float x, float y) {
1399 mInputReceiver->consumeDragEvent(isExiting, x, y);
1400 }
1401
Antonio Kantekf16f2832021-09-28 04:39:20 +00001402 void consumeTouchModeEvent(bool inTouchMode) {
1403 ASSERT_NE(mInputReceiver, nullptr)
1404 << "Cannot consume events from a window with no receiver";
1405 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1406 }
1407
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001408 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001409 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001410 }
1411
1412 void finishEvent(uint32_t sequenceNum) {
1413 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1414 mInputReceiver->finishEvent(sequenceNum);
1415 }
1416
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001417 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1418 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1419 mInputReceiver->sendTimeline(inputEventId, timeline);
1420 }
1421
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001422 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001423 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001424 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001425 return; // Can't receive events if the window does not have input channel
1426 }
1427 ASSERT_NE(nullptr, mInputReceiver)
1428 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001429 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001430 }
1431
chaviwaf87b3e2019-10-01 16:59:28 -07001432 sp<IBinder> getToken() { return mInfo.token; }
1433
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001434 const std::string& getName() { return mName; }
1435
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001436 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001437 mInfo.ownerPid = ownerPid;
1438 mInfo.ownerUid = ownerUid;
1439 }
1440
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001441 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001442
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001443 void destroyReceiver() { mInputReceiver = nullptr; }
1444
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001445 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1446
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001447 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001448 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001449 if (mInputReceiver == nullptr) {
1450 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1451 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001452 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001453 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001454 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001455 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001456 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001457 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001458 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001459
1460private:
1461 FakeWindowHandle(std::string name) : mName(name){};
1462 const std::string mName;
1463 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1464 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1465 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001466
1467 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
1468 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
1469 if (mInputReceiver == nullptr) {
1470 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1471 return std::make_pair(std::nullopt, nullptr);
1472 }
1473 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1474 const auto& [_, event] = out;
1475 expectReceivedEventTraced(event);
1476 return std::move(out);
1477 }
1478
1479 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
1480 if (!event) {
1481 return;
1482 }
1483
1484 switch (event->getType()) {
1485 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001486 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001487 break;
1488 }
1489 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +00001490 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
1491 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +00001492 break;
1493 }
1494 default:
1495 break;
1496 }
1497 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001498};
1499
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001500std::atomic<int32_t> FakeWindowHandle::sId{1};
1501
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001502class FakeMonitorReceiver {
1503public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001504 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1505 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001506
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001507 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001508
1509 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001510 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1511 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001512 }
1513
1514 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001515 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1516 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001517 }
1518
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001519 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001520
1521 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001522 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1523 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001524 }
1525
1526 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001527 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1528 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001529 }
1530
1531 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001532 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1533 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001534 }
1535
1536 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001537 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001538 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1539 WithDisplayId(expectedDisplayId),
1540 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1541 }
1542
1543 void consumeMotionPointerDown(int32_t pointerIdx) {
1544 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1545 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001546 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1547 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001548 }
1549
1550 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001551 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001552 }
1553
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001554 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001555
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001556 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001557
1558private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001559 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001560};
1561
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001562static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001563 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001564 int32_t displayId = ADISPLAY_ID_NONE,
1565 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001566 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001567 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001568 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001569 KeyEvent event;
1570 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1571
1572 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001573 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001574 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1575 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001576
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001577 if (!allowKeyRepeat) {
1578 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1579 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001580 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001581 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001582}
1583
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001584static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1585 InputEventInjectionResult result =
1586 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1587 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1588 if (result != InputEventInjectionResult::TIMED_OUT) {
1589 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1590 }
1591}
1592
1593static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001594 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001595 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001596}
1597
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001598// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1599// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1600// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001601static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1602 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001603 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001604 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001605 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001606}
1607
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001609 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001610 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001611}
1612
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001613static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001615 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001616 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001617 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1619 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001620}
1621
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001622static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001623 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1624 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001625 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001626 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1627 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001628 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001629 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001630 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001631 MotionEventBuilder motionBuilder =
1632 MotionEventBuilder(action, source)
1633 .displayId(displayId)
1634 .eventTime(eventTime)
1635 .rawXCursorPosition(cursorPosition.x)
1636 .rawYCursorPosition(cursorPosition.y)
1637 .pointer(
1638 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1639 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1640 motionBuilder.downTime(eventTime);
1641 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001642
1643 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001644 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1645 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001646}
1647
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001648static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1649 int32_t displayId,
1650 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001651 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001652}
1653
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001654static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1655 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001656 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001657 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001658}
1659
Jackal Guof9696682018-10-05 12:23:23 +08001660static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1661 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1662 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001663 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1664 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1665 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001666
1667 return args;
1668}
1669
Josep del Riob3981622023-04-18 15:49:45 +00001670static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1671 int32_t displayId = ADISPLAY_ID_NONE) {
1672 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1673 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001674 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1675 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1676 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001677
1678 return args;
1679}
1680
1681static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1682 int32_t displayId = ADISPLAY_ID_NONE) {
1683 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1684 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001685 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1686 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1687 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001688
1689 return args;
1690}
1691
Prabir Pradhan678438e2023-04-13 19:32:51 +00001692[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1693 int32_t displayId,
1694 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001695 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001696 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1697 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1698 }
1699
chaviwd1c23182019-12-20 18:44:56 -08001700 PointerProperties pointerProperties[pointerCount];
1701 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001702
chaviwd1c23182019-12-20 18:44:56 -08001703 for (size_t i = 0; i < pointerCount; i++) {
1704 pointerProperties[i].clear();
1705 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001706 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001707
chaviwd1c23182019-12-20 18:44:56 -08001708 pointerCoords[i].clear();
1709 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1710 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1711 }
Jackal Guof9696682018-10-05 12:23:23 +08001712
1713 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1714 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001715 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1716 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1717 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001718 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001719 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001720 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001721 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001722
1723 return args;
1724}
1725
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001726static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1727 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1728}
1729
chaviwd1c23182019-12-20 18:44:56 -08001730static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1731 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1732}
1733
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001734static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1735 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001736 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1737 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001738}
1739
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001740} // namespace
1741
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001742/**
1743 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1744 * broken channel.
1745 */
1746TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1748 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001749 sp<FakeWindowHandle>::make(application, mDispatcher,
1750 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001751
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001752 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001753
1754 // Window closes its channel, but the window remains.
1755 window->destroyReceiver();
1756 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1757}
1758
Arthur Hungb92218b2018-08-14 12:00:21 +08001759TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001760 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001761 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1762 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001763
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001764 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001768
1769 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001770 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001771}
1772
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001773using InputDispatcherDeathTest = InputDispatcherTest;
1774
1775/**
1776 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1777 * should crash.
1778 */
1779TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1780 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1781 ScopedSilentDeath _silentDeath;
1782
1783 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1784 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1785 "Fake Window", ADISPLAY_ID_DEFAULT);
1786 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1787 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1788 "Incorrect WindowInfosUpdate provided");
1789}
1790
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001791TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1792 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001793 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1794 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001795
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001796 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001797 // Inject a MotionEvent to an unknown display.
1798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001799 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1801
1802 // Window should receive motion event.
1803 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1804}
1805
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001806/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001807 * Calling onWindowInfosChanged once should not cause any issues.
1808 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001809 * called twice.
1810 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001811TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001813 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1814 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001815 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001816
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001817 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001819 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001820 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001821 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001822
1823 // Window should receive motion event.
1824 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1825}
1826
1827/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001828 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001829 */
1830TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001831 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001832 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1833 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001834 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001835
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001836 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1837 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001838 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001839 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001840 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001841 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001842
1843 // Window should receive motion event.
1844 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1845}
1846
Arthur Hungb92218b2018-08-14 12:00:21 +08001847// The foreground window should receive the first touch down event.
1848TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001850 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001851 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001852 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001853 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001855 mDispatcher->onWindowInfosChanged(
1856 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001858 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001860
1861 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001862 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001863 windowSecond->assertNoEvents();
1864}
1865
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001866/**
1867 * Two windows: A top window, and a wallpaper behind the window.
1868 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1869 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001870 * 1. foregroundWindow <-- dup touch to wallpaper
1871 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001872 */
1873TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1875 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001876 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001877 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001878 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001879 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001880 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001881
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001882 mDispatcher->onWindowInfosChanged(
1883 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001885 injectMotionEvent(*mDispatcher,
1886 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1887 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1888 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1890
1891 // Both foreground window and its wallpaper should receive the touch down
1892 foregroundWindow->consumeMotionDown();
1893 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1894
1895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001896 injectMotionEvent(*mDispatcher,
1897 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1898 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1899 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001900 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1901
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001902 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001903 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1904
1905 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001906 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001907 foregroundWindow->consumeMotionCancel();
1908 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1909 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1910}
1911
1912/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001913 * Two fingers down on the window, and lift off the first finger.
1914 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1915 * contains a single pointer.
1916 */
1917TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1919 sp<FakeWindowHandle> window =
1920 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001922 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001923 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001924 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1925 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1926 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001927 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001928 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1929 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1930 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1931 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001932 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001933 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1934 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1935 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1936 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001937 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1938 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1939 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1940
1941 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001942 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001943 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1944 window->consumeMotionEvent(
1945 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1946}
1947
1948/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001949 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1950 * with the following differences:
1951 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1952 * clean up the connection.
1953 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1954 * Ensure that there's no crash in the dispatcher.
1955 */
1956TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1958 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001959 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001960 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001961 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001962 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001963 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001964
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001965 mDispatcher->onWindowInfosChanged(
1966 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001969 {100, 200}))
1970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1971
1972 // Both foreground window and its wallpaper should receive the touch down
1973 foregroundWindow->consumeMotionDown();
1974 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1975
1976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001977 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001978 ADISPLAY_ID_DEFAULT, {110, 200}))
1979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1980
1981 foregroundWindow->consumeMotionMove();
1982 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1983
1984 // Wallpaper closes its channel, but the window remains.
1985 wallpaperWindow->destroyReceiver();
1986 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1987
1988 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1989 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001990 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001991 foregroundWindow->consumeMotionCancel();
1992}
1993
Arthur Hungc539dbb2022-12-08 07:45:36 +00001994class ShouldSplitTouchFixture : public InputDispatcherTest,
1995 public ::testing::WithParamInterface<bool> {};
1996INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1997 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001998/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001999 * A single window that receives touch (on top), and a wallpaper window underneath it.
2000 * The top window gets a multitouch gesture.
2001 * Ensure that wallpaper gets the same gesture.
2002 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00002003TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002004 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002005 sp<FakeWindowHandle> foregroundWindow =
2006 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
2007 foregroundWindow->setDupTouchToWallpaper(true);
2008 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002009
2010 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002011 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002012 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002013
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002014 mDispatcher->onWindowInfosChanged(
2015 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002016
2017 // Touch down on top window
2018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002019 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002020 {100, 100}))
2021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2022
2023 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00002024 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002025 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2026
2027 // Second finger down on the top window
2028 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002029 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002030 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002031 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2032 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002033 .build();
2034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002035 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002036 InputEventInjectionSync::WAIT_FOR_RESULT))
2037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2038
Harry Cutts33476232023-01-30 19:57:29 +00002039 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2040 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002041 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002042
2043 const MotionEvent secondFingerUpEvent =
2044 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2045 .displayId(ADISPLAY_ID_DEFAULT)
2046 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002047 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2048 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002049 .build();
2050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002051 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002052 InputEventInjectionSync::WAIT_FOR_RESULT))
2053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2054 foregroundWindow->consumeMotionPointerUp(0);
2055 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2056
2057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002058 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002059 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2060 AINPUT_SOURCE_TOUCHSCREEN)
2061 .displayId(ADISPLAY_ID_DEFAULT)
2062 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002063 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002064 .x(100)
2065 .y(100))
2066 .build(),
2067 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002068 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2069 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2070 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002071}
2072
2073/**
2074 * Two windows: a window on the left and window on the right.
2075 * A third window, wallpaper, is behind both windows, and spans both top windows.
2076 * The first touch down goes to the left window. A second pointer touches down on the right window.
2077 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2078 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2079 * ACTION_POINTER_DOWN(1).
2080 */
2081TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2083 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002084 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002085 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002086 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002087
2088 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002089 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002090 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002091 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002092
2093 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002094 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002095 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002096 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002098 mDispatcher->onWindowInfosChanged(
2099 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2100 {},
2101 0,
2102 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002103
2104 // Touch down on left window
2105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002106 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002107 {100, 100}))
2108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2109
2110 // Both foreground window and its wallpaper should receive the touch down
2111 leftWindow->consumeMotionDown();
2112 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2113
2114 // Second finger down on the right window
2115 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002116 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002117 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002118 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2119 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002120 .build();
2121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002122 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002123 InputEventInjectionSync::WAIT_FOR_RESULT))
2124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2125
2126 leftWindow->consumeMotionMove();
2127 // Since the touch is split, right window gets ACTION_DOWN
2128 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002129 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002130 expectedWallpaperFlags);
2131
2132 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002133 mDispatcher->onWindowInfosChanged(
2134 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002135 leftWindow->consumeMotionCancel();
2136 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2137 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2138
2139 // The pointer that's still down on the right window moves, and goes to the right window only.
2140 // As far as the dispatcher's concerned though, both pointers are still present.
2141 const MotionEvent secondFingerMoveEvent =
2142 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2143 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002144 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2145 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002146 .build();
2147 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002148 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002149 InputEventInjectionSync::WAIT_FOR_RESULT));
2150 rightWindow->consumeMotionMove();
2151
2152 leftWindow->assertNoEvents();
2153 rightWindow->assertNoEvents();
2154 wallpaperWindow->assertNoEvents();
2155}
2156
Arthur Hungc539dbb2022-12-08 07:45:36 +00002157/**
2158 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2159 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2160 * The right window should receive ACTION_DOWN.
2161 */
2162TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002163 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002164 sp<FakeWindowHandle> leftWindow =
2165 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2166 leftWindow->setFrame(Rect(0, 0, 200, 200));
2167 leftWindow->setDupTouchToWallpaper(true);
2168 leftWindow->setSlippery(true);
2169
2170 sp<FakeWindowHandle> rightWindow =
2171 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2172 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002173
2174 sp<FakeWindowHandle> wallpaperWindow =
2175 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2176 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002177
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002178 mDispatcher->onWindowInfosChanged(
2179 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2180 {},
2181 0,
2182 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002183
Arthur Hungc539dbb2022-12-08 07:45:36 +00002184 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002186 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002187 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002189
2190 // Both foreground window and its wallpaper should receive the touch down
2191 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002192 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2193
Arthur Hungc539dbb2022-12-08 07:45:36 +00002194 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002196 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002197 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002198 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2199
Arthur Hungc539dbb2022-12-08 07:45:36 +00002200 leftWindow->consumeMotionCancel();
2201 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2202 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002203}
2204
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002205/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002206 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2207 * interactive, it might stop sending this flag.
2208 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2209 * to have a consistent input stream.
2210 *
2211 * Test procedure:
2212 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2213 * DOWN (new gesture).
2214 *
2215 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2216 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2217 *
2218 * We technically just need a single window here, but we are using two windows (spy on top and a
2219 * regular window below) to emulate the actual situation where it happens on the device.
2220 */
2221TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2222 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2223 sp<FakeWindowHandle> spyWindow =
2224 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2225 spyWindow->setFrame(Rect(0, 0, 200, 200));
2226 spyWindow->setTrustedOverlay(true);
2227 spyWindow->setSpy(true);
2228
2229 sp<FakeWindowHandle> window =
2230 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2231 window->setFrame(Rect(0, 0, 200, 200));
2232
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002233 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002234 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002235
2236 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002237 mDispatcher->notifyMotion(
2238 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2239 .deviceId(touchDeviceId)
2240 .policyFlags(DEFAULT_POLICY_FLAGS)
2241 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2242 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002243
Prabir Pradhan678438e2023-04-13 19:32:51 +00002244 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2245 .deviceId(touchDeviceId)
2246 .policyFlags(DEFAULT_POLICY_FLAGS)
2247 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2248 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2249 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002250 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2251 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2252 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2253 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2254
2255 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002256 mDispatcher->notifyMotion(
2257 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2258 .deviceId(touchDeviceId)
2259 .policyFlags(0)
2260 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2261 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2262 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002263 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2264 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2265
2266 // We don't need to reset the device to reproduce the issue, but the reset event typically
2267 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002268 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002269
2270 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002271 mDispatcher->notifyMotion(
2272 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2273 .deviceId(touchDeviceId)
2274 .policyFlags(DEFAULT_POLICY_FLAGS)
2275 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2276 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002277 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2278 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2279
2280 // No more events
2281 spyWindow->assertNoEvents();
2282 window->assertNoEvents();
2283}
2284
2285/**
Linnan Li907ae732023-09-05 17:14:21 +08002286 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2287 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2288 * interactive, it might stop sending this flag.
2289 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2290 * the consistency of the hover event in this case.
2291 *
2292 * Test procedure:
2293 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2294 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2295 *
2296 * We expect to receive two full streams of hover events.
2297 */
2298TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2299 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2300
2301 sp<FakeWindowHandle> window =
2302 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2303 window->setFrame(Rect(0, 0, 300, 300));
2304
2305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2306
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2308 .policyFlags(DEFAULT_POLICY_FLAGS)
2309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2310 .build());
2311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2312
2313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2314 .policyFlags(DEFAULT_POLICY_FLAGS)
2315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2316 .build());
2317 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2318
2319 // Send hover exit without the default policy flags.
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2321 .policyFlags(0)
2322 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2323 .build());
2324
2325 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2326
2327 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2328 // right event.
2329 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2330 .policyFlags(DEFAULT_POLICY_FLAGS)
2331 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2332 .build());
2333 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2334
2335 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2336 .policyFlags(DEFAULT_POLICY_FLAGS)
2337 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2338 .build());
2339 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2340
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2342 .policyFlags(DEFAULT_POLICY_FLAGS)
2343 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2344 .build());
2345 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2346}
2347
2348/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002349 * Two windows: a window on the left and a window on the right.
2350 * Mouse is hovered from the right window into the left window.
2351 * Next, we tap on the left window, where the cursor was last seen.
2352 * The second tap is done onto the right window.
2353 * The mouse and tap are from two different devices.
2354 * We technically don't need to set the downtime / eventtime for these events, but setting these
2355 * explicitly helps during debugging.
2356 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2357 * In the buggy implementation, a tap on the right window would cause a crash.
2358 */
2359TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2361 sp<FakeWindowHandle> leftWindow =
2362 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2363 leftWindow->setFrame(Rect(0, 0, 200, 200));
2364
2365 sp<FakeWindowHandle> rightWindow =
2366 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2367 rightWindow->setFrame(Rect(200, 0, 400, 200));
2368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002369 mDispatcher->onWindowInfosChanged(
2370 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002371 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2372 // stale.
2373 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2374 const int32_t mouseDeviceId = 6;
2375 const int32_t touchDeviceId = 4;
2376 // Move the cursor from right
2377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002378 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002379 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2380 AINPUT_SOURCE_MOUSE)
2381 .deviceId(mouseDeviceId)
2382 .downTime(baseTime + 10)
2383 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002384 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002385 .build()));
2386 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2387
2388 // .. to the left window
2389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002390 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002391 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2392 AINPUT_SOURCE_MOUSE)
2393 .deviceId(mouseDeviceId)
2394 .downTime(baseTime + 10)
2395 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002396 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002397 .build()));
2398 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2399 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2400 // Now tap the left window
2401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002402 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002403 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2404 AINPUT_SOURCE_TOUCHSCREEN)
2405 .deviceId(touchDeviceId)
2406 .downTime(baseTime + 40)
2407 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002408 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002409 .build()));
2410 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2411 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2412
2413 // release tap
2414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002415 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002416 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2417 AINPUT_SOURCE_TOUCHSCREEN)
2418 .deviceId(touchDeviceId)
2419 .downTime(baseTime + 40)
2420 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002421 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002422 .build()));
2423 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2424
2425 // Tap the window on the right
2426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002427 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002428 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2429 AINPUT_SOURCE_TOUCHSCREEN)
2430 .deviceId(touchDeviceId)
2431 .downTime(baseTime + 60)
2432 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002433 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002434 .build()));
2435 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2436
2437 // release tap
2438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002439 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002440 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2441 AINPUT_SOURCE_TOUCHSCREEN)
2442 .deviceId(touchDeviceId)
2443 .downTime(baseTime + 60)
2444 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002445 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002446 .build()));
2447 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2448
2449 // No more events
2450 leftWindow->assertNoEvents();
2451 rightWindow->assertNoEvents();
2452}
2453
2454/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002455 * Start hovering in a window. While this hover is still active, make another window appear on top.
2456 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2457 * While the top window is present, the hovering is stopped.
2458 * Later, hovering gets resumed again.
2459 * Ensure that new hover gesture is handled correctly.
2460 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2461 * to the window that's currently being hovered over.
2462 */
2463TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2465 sp<FakeWindowHandle> window =
2466 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2467 window->setFrame(Rect(0, 0, 200, 200));
2468
2469 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002470 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002471
2472 // Start hovering in the window
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2475 .build());
2476 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2477
2478 // Now, an obscuring window appears!
2479 sp<FakeWindowHandle> obscuringWindow =
2480 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2481 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002482 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002483 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2484 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2485 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2486 obscuringWindow->setNoInputChannel(true);
2487 obscuringWindow->setFocusable(false);
2488 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002489 mDispatcher->onWindowInfosChanged(
2490 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002491
2492 // While this new obscuring window is present, the hovering is stopped
2493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2494 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2495 .build());
2496 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2497
2498 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002499 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002500
2501 // And a new hover gesture starts.
2502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2503 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2504 .build());
2505 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2506}
2507
2508/**
2509 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2510 * the obscuring window.
2511 */
2512TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2513 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2514 sp<FakeWindowHandle> window =
2515 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2516 window->setFrame(Rect(0, 0, 200, 200));
2517
2518 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002520
2521 // Start hovering in the window
2522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2523 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2524 .build());
2525 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2526
2527 // Now, an obscuring window appears!
2528 sp<FakeWindowHandle> obscuringWindow =
2529 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2530 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002531 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002532 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2533 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2534 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2535 obscuringWindow->setNoInputChannel(true);
2536 obscuringWindow->setFocusable(false);
2537 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002538 mDispatcher->onWindowInfosChanged(
2539 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002540
2541 // While this new obscuring window is present, the hovering continues. The event can't go to the
2542 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2544 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2545 .build());
2546 obscuringWindow->assertNoEvents();
2547 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2548
2549 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002550 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002551
2552 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2553 // so it should generate a HOVER_ENTER
2554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2556 .build());
2557 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2558
2559 // Now the MOVE should be getting dispatched normally
2560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2561 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2562 .build());
2563 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2564}
2565
2566/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002567 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2568 * events are delivered to the window.
2569 */
2570TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2572 sp<FakeWindowHandle> window =
2573 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2574 window->setFrame(Rect(0, 0, 200, 200));
2575 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2576
2577 // Start hovering in the window
2578 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2579 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2580 .build());
2581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2582
2583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2585 .build());
2586 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2587
2588 // Scroll with the mouse
2589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2590 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2591 .build());
2592 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2593}
2594
2595using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2596
2597/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002598 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2599 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002600 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002601TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002602 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2603 sp<FakeWindowHandle> window =
2604 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2605 window->setFrame(Rect(0, 0, 200, 200));
2606
2607 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2608
2609 constexpr int32_t touchDeviceId = 4;
2610 constexpr int32_t stylusDeviceId = 2;
2611
2612 // Stylus down
2613 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2614 .deviceId(stylusDeviceId)
2615 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2616 .build());
2617 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2618
2619 // Touch down
2620 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2621 .deviceId(touchDeviceId)
2622 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2623 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002624
2625 // Touch move
2626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2627 .deviceId(touchDeviceId)
2628 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2629 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002630 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002631
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002632 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2634 .deviceId(stylusDeviceId)
2635 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2636 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002637 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2638 WithCoords(101, 111)));
2639
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002640 window->assertNoEvents();
2641}
2642
2643/**
2644 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002646 * Similar test as above, but with added SPY window.
2647 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002648TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002649 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2650 sp<FakeWindowHandle> window =
2651 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2652 sp<FakeWindowHandle> spyWindow =
2653 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2654 spyWindow->setFrame(Rect(0, 0, 200, 200));
2655 spyWindow->setTrustedOverlay(true);
2656 spyWindow->setSpy(true);
2657 window->setFrame(Rect(0, 0, 200, 200));
2658
2659 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2660
2661 constexpr int32_t touchDeviceId = 4;
2662 constexpr int32_t stylusDeviceId = 2;
2663
2664 // Stylus down
2665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2666 .deviceId(stylusDeviceId)
2667 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2668 .build());
2669 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2670 spyWindow->consumeMotionEvent(
2671 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2672
2673 // Touch down
2674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2675 .deviceId(touchDeviceId)
2676 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2677 .build());
2678
2679 // Touch move
2680 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2681 .deviceId(touchDeviceId)
2682 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2683 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002684
2685 // Touch is ignored because stylus is already down
2686
2687 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002688 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2689 .deviceId(stylusDeviceId)
2690 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2691 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002692 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2693 WithCoords(101, 111)));
2694 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2695 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002696
2697 window->assertNoEvents();
2698 spyWindow->assertNoEvents();
2699}
2700
2701/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002702 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002703 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002704 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002705TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2707 sp<FakeWindowHandle> window =
2708 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2709 window->setFrame(Rect(0, 0, 200, 200));
2710
2711 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2712
2713 constexpr int32_t touchDeviceId = 4;
2714 constexpr int32_t stylusDeviceId = 2;
2715
2716 // Stylus down on the window
2717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2718 .deviceId(stylusDeviceId)
2719 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2720 .build());
2721 window->consumeMotionEvent(
2722 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2723
2724 // Touch down on window
2725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2726 .deviceId(touchDeviceId)
2727 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2728 .build());
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2730 .deviceId(touchDeviceId)
2731 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2732 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002733
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002734 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002735
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002736 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2738 .deviceId(stylusDeviceId)
2739 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2740 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002741 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2742 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002743
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002744 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2746 .deviceId(touchDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2748 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002749 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002750}
2751
2752/**
2753 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002754 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002755 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002756TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002757 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2758 sp<FakeWindowHandle> window =
2759 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2760 window->setFrame(Rect(0, 0, 200, 200));
2761
2762 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2763
2764 constexpr int32_t touchDeviceId = 4;
2765 constexpr int32_t stylusDeviceId = 2;
2766
2767 // Touch down on window
2768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2769 .deviceId(touchDeviceId)
2770 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2771 .build());
2772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2773 .deviceId(touchDeviceId)
2774 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2775 .build());
2776 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2777 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2778
2779 // Stylus hover on the window
2780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2781 .deviceId(stylusDeviceId)
2782 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2783 .build());
2784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2785 .deviceId(stylusDeviceId)
2786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2787 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002788 // Stylus hover movement causes touch to be canceled
2789 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2790 WithCoords(141, 146)));
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2792 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2793 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2794 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002795
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002796 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2798 .deviceId(touchDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2800 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002801
2802 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002803}
2804
2805/**
2806 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2807 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2808 * become active.
2809 */
2810TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2812 sp<FakeWindowHandle> window =
2813 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2814 window->setFrame(Rect(0, 0, 200, 200));
2815
2816 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2817
2818 constexpr int32_t stylusDeviceId1 = 3;
2819 constexpr int32_t stylusDeviceId2 = 5;
2820
2821 // Touch down on window
2822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2823 .deviceId(stylusDeviceId1)
2824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2825 .build());
2826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2827 .deviceId(stylusDeviceId1)
2828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2829 .build());
2830 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2831 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2832
2833 // Second stylus down
2834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2835 .deviceId(stylusDeviceId2)
2836 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2837 .build());
2838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2839 .deviceId(stylusDeviceId2)
2840 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2841 .build());
2842
2843 // First stylus is canceled, second one takes over.
2844 window->consumeMotionEvent(
2845 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2846 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2847 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2848
2849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2850 .deviceId(stylusDeviceId1)
2851 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2852 .build());
2853 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002854 window->assertNoEvents();
2855}
2856
2857/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002858 * One window. Touch down on the window. Then, stylus down on the window from another device.
2859 * Ensure that is canceled, because stylus down should be preferred over touch.
2860 */
2861TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2862 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2863 sp<FakeWindowHandle> window =
2864 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2865 window->setFrame(Rect(0, 0, 200, 200));
2866
2867 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2868
2869 constexpr int32_t touchDeviceId = 4;
2870 constexpr int32_t stylusDeviceId = 2;
2871
2872 // Touch down on window
2873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2874 .deviceId(touchDeviceId)
2875 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2876 .build());
2877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2878 .deviceId(touchDeviceId)
2879 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2880 .build());
2881 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2882 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2883
2884 // Stylus down on the window
2885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2886 .deviceId(stylusDeviceId)
2887 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2888 .build());
2889 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2890 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2891
2892 // Subsequent stylus movements are delivered correctly
2893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2894 .deviceId(stylusDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2896 .build());
2897 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2898 WithCoords(101, 111)));
2899}
2900
2901/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002902 * Two windows: a window on the left and a window on the right.
2903 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2904 * down. Then, on the left window, also place second touch pointer down.
2905 * This test tries to reproduce a crash.
2906 * In the buggy implementation, second pointer down on the left window would cause a crash.
2907 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002908TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002909 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2910 sp<FakeWindowHandle> leftWindow =
2911 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2912 leftWindow->setFrame(Rect(0, 0, 200, 200));
2913
2914 sp<FakeWindowHandle> rightWindow =
2915 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2916 rightWindow->setFrame(Rect(200, 0, 400, 200));
2917
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002918 mDispatcher->onWindowInfosChanged(
2919 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002920
2921 const int32_t touchDeviceId = 4;
2922 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002923
2924 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2926 .deviceId(mouseDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2928 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002929 leftWindow->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2931
2932 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002933 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2934 .deviceId(mouseDeviceId)
2935 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2936 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2937 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002938
2939 leftWindow->consumeMotionEvent(
2940 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2941 leftWindow->consumeMotionEvent(
2942 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2943
Prabir Pradhan678438e2023-04-13 19:32:51 +00002944 mDispatcher->notifyMotion(
2945 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2946 .deviceId(mouseDeviceId)
2947 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2948 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2950 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002951 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2952
2953 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2955 .deviceId(touchDeviceId)
2956 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2957 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002958 leftWindow->assertNoEvents();
2959
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002960 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2961
2962 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002963 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2964 .deviceId(touchDeviceId)
2965 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2966 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2967 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002968 // Since this is now a new splittable pointer going down on the left window, and it's coming
2969 // from a different device, the current gesture in the left window (pointer down) should first
2970 // be canceled.
2971 leftWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002973 leftWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2975 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2976 // current implementation.
2977 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2978 rightWindow->consumeMotionEvent(
2979 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2980
2981 leftWindow->assertNoEvents();
2982 rightWindow->assertNoEvents();
2983}
2984
2985/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002986 * Two windows: a window on the left and a window on the right.
2987 * Mouse is hovered on the left window and stylus is hovered on the right window.
2988 */
2989TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2990 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2991 sp<FakeWindowHandle> leftWindow =
2992 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2993 leftWindow->setFrame(Rect(0, 0, 200, 200));
2994
2995 sp<FakeWindowHandle> rightWindow =
2996 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2997 rightWindow->setFrame(Rect(200, 0, 400, 200));
2998
2999 mDispatcher->onWindowInfosChanged(
3000 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3001
3002 const int32_t stylusDeviceId = 3;
3003 const int32_t mouseDeviceId = 6;
3004
3005 // Start hovering over the left window
3006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3007 .deviceId(mouseDeviceId)
3008 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
3009 .build());
3010 leftWindow->consumeMotionEvent(
3011 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3012
3013 // Stylus hovered on right window
3014 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3015 .deviceId(stylusDeviceId)
3016 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
3017 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003018 rightWindow->consumeMotionEvent(
3019 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3020
3021 // Subsequent HOVER_MOVE events are dispatched correctly.
3022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3023 .deviceId(mouseDeviceId)
3024 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
3025 .build());
3026 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003027 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003028
3029 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3030 .deviceId(stylusDeviceId)
3031 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
3032 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003033 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003034 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003035
3036 leftWindow->assertNoEvents();
3037 rightWindow->assertNoEvents();
3038}
3039
3040/**
3041 * Three windows: a window on the left and a window on the right.
3042 * And a spy window that's positioned above all of them.
3043 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3044 * Check the stream that's received by the spy.
3045 */
3046TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3048
3049 sp<FakeWindowHandle> spyWindow =
3050 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3051 spyWindow->setFrame(Rect(0, 0, 400, 400));
3052 spyWindow->setTrustedOverlay(true);
3053 spyWindow->setSpy(true);
3054
3055 sp<FakeWindowHandle> leftWindow =
3056 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3057 leftWindow->setFrame(Rect(0, 0, 200, 200));
3058
3059 sp<FakeWindowHandle> rightWindow =
3060 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3061
3062 rightWindow->setFrame(Rect(200, 0, 400, 200));
3063
3064 mDispatcher->onWindowInfosChanged(
3065 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3066
3067 const int32_t stylusDeviceId = 1;
3068 const int32_t touchDeviceId = 2;
3069
3070 // Stylus down on the left window
3071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3072 .deviceId(stylusDeviceId)
3073 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3074 .build());
3075 leftWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3077 spyWindow->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3079
3080 // Touch down on the right window
3081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3082 .deviceId(touchDeviceId)
3083 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3084 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003085 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003086 rightWindow->consumeMotionEvent(
3087 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003088
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003089 // Spy window does not receive touch events, because stylus events take precedence, and it
3090 // already has an active stylus gesture.
3091
3092 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3094 .deviceId(stylusDeviceId)
3095 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3096 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003097 leftWindow->consumeMotionEvent(
3098 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3099 spyWindow->consumeMotionEvent(
3100 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003101
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003102 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3104 .deviceId(touchDeviceId)
3105 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3106 .build());
3107 rightWindow->consumeMotionEvent(
3108 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003109
3110 spyWindow->assertNoEvents();
3111 leftWindow->assertNoEvents();
3112 rightWindow->assertNoEvents();
3113}
3114
3115/**
3116 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3117 * both.
3118 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003119 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003120 * At the same time, left and right should be getting independent streams of hovering and touch,
3121 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003122 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003123TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3125
3126 sp<FakeWindowHandle> spyWindow =
3127 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3128 spyWindow->setFrame(Rect(0, 0, 400, 400));
3129 spyWindow->setTrustedOverlay(true);
3130 spyWindow->setSpy(true);
3131
3132 sp<FakeWindowHandle> leftWindow =
3133 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3134 leftWindow->setFrame(Rect(0, 0, 200, 200));
3135
3136 sp<FakeWindowHandle> rightWindow =
3137 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3138 rightWindow->setFrame(Rect(200, 0, 400, 200));
3139
3140 mDispatcher->onWindowInfosChanged(
3141 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3142
3143 const int32_t stylusDeviceId = 1;
3144 const int32_t touchDeviceId = 2;
3145
3146 // Stylus hover on the left window
3147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3148 .deviceId(stylusDeviceId)
3149 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3150 .build());
3151 leftWindow->consumeMotionEvent(
3152 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3153 spyWindow->consumeMotionEvent(
3154 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3155
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003156 // Touch down on the right window. Spy doesn't receive this touch because it already has
3157 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3159 .deviceId(touchDeviceId)
3160 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3161 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003162 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003163 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003164 rightWindow->consumeMotionEvent(
3165 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3166
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003167 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003168 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3169 .deviceId(stylusDeviceId)
3170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3171 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003172 leftWindow->consumeMotionEvent(
3173 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003174 spyWindow->consumeMotionEvent(
3175 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003176
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003177 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003178 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3179 .deviceId(touchDeviceId)
3180 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3181 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003182 rightWindow->consumeMotionEvent(
3183 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3184
3185 spyWindow->assertNoEvents();
3186 leftWindow->assertNoEvents();
3187 rightWindow->assertNoEvents();
3188}
3189
3190/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003191 * On a single window, use two different devices: mouse and touch.
3192 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3193 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3194 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3195 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3196 * represent a new gesture.
3197 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003198TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3200 sp<FakeWindowHandle> window =
3201 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3202 window->setFrame(Rect(0, 0, 400, 400));
3203
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205
3206 const int32_t touchDeviceId = 4;
3207 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003208
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003209 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3211 .deviceId(touchDeviceId)
3212 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3213 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003214 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003215 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3216 .deviceId(touchDeviceId)
3217 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3218 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3219 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003220 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003221 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3222 .deviceId(touchDeviceId)
3223 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3224 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3225 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003226 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3227 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3228 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3229
3230 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003231 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
3233 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3234 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3235 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003236
3237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003238 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3240
Prabir Pradhan678438e2023-04-13 19:32:51 +00003241 mDispatcher->notifyMotion(
3242 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3243 .deviceId(mouseDeviceId)
3244 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3245 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3246 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3247 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003248 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3249
3250 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003251 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3252 .deviceId(touchDeviceId)
3253 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3254 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3255 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003256 // Since we already canceled this touch gesture, it will be ignored until a completely new
3257 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3258 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3259 // However, mouse movements should continue to work.
3260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3261 .deviceId(mouseDeviceId)
3262 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3263 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3264 .build());
3265 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3266
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003267 window->assertNoEvents();
3268}
3269
3270/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003271 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3272 * the injected event.
3273 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003274TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3276 sp<FakeWindowHandle> window =
3277 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3278 window->setFrame(Rect(0, 0, 400, 400));
3279
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003280 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003281
3282 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003283 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3284 // completion.
3285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003286 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003287 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3288 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003289 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003290 .build()));
3291 window->consumeMotionEvent(
3292 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3293
3294 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3295 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3297 .deviceId(touchDeviceId)
3298 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3299 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003300
3301 window->consumeMotionEvent(
3302 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3303 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3304}
3305
3306/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003307 * This test is similar to the test above, but the sequence of injected events is different.
3308 *
3309 * Two windows: a window on the left and a window on the right.
3310 * Mouse is hovered over the left window.
3311 * Next, we tap on the left window, where the cursor was last seen.
3312 *
3313 * After that, we inject one finger down onto the right window, and then a second finger down onto
3314 * the left window.
3315 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3316 * window (first), and then another on the left window (second).
3317 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3318 * In the buggy implementation, second finger down on the left window would cause a crash.
3319 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003320TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3322 sp<FakeWindowHandle> leftWindow =
3323 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3324 leftWindow->setFrame(Rect(0, 0, 200, 200));
3325
3326 sp<FakeWindowHandle> rightWindow =
3327 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3328 rightWindow->setFrame(Rect(200, 0, 400, 200));
3329
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003330 mDispatcher->onWindowInfosChanged(
3331 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003332
3333 const int32_t mouseDeviceId = 6;
3334 const int32_t touchDeviceId = 4;
3335 // Hover over the left window. Keep the cursor there.
3336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003338 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3339 AINPUT_SOURCE_MOUSE)
3340 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003342 .build()));
3343 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3344
3345 // Tap on left window
3346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003348 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3349 AINPUT_SOURCE_TOUCHSCREEN)
3350 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003352 .build()));
3353
3354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003356 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3357 AINPUT_SOURCE_TOUCHSCREEN)
3358 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003360 .build()));
3361 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3362 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3363 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3364
3365 // First finger down on right window
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003368 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3369 AINPUT_SOURCE_TOUCHSCREEN)
3370 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003371 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003372 .build()));
3373 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3374
3375 // Second finger down on the left window
3376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003378 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3379 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003380 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3381 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 .build()));
3383 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3384 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3385
3386 // No more events
3387 leftWindow->assertNoEvents();
3388 rightWindow->assertNoEvents();
3389}
3390
3391/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003392 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3393 * While the touch is down, new hover events from the stylus device should be ignored. After the
3394 * touch is gone, stylus hovering should start working again.
3395 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003396TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3398 sp<FakeWindowHandle> window =
3399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3400 window->setFrame(Rect(0, 0, 200, 200));
3401
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003403
3404 const int32_t stylusDeviceId = 5;
3405 const int32_t touchDeviceId = 4;
3406 // Start hovering with stylus
3407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003408 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003409 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003410 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003411 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003412 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003413 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003414
3415 // Finger down on the window
3416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003417 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003418 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003419 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003420 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003421 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003422 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003423
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003424 // Continue hovering with stylus.
3425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003426 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003427 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3428 AINPUT_SOURCE_STYLUS)
3429 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003430 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003431 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003432 // Hovers continue to work
3433 window->consumeMotionEvent(
3434 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003435
3436 // Lift up the finger
3437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003438 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003439 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3440 AINPUT_SOURCE_TOUCHSCREEN)
3441 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003442 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003443 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003444
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003445 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003446 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003447 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3448 AINPUT_SOURCE_STYLUS)
3449 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003450 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003451 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003452 window->consumeMotionEvent(
3453 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003454 window->assertNoEvents();
3455}
3456
3457/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003458 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3459 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3460 *
3461 * Two windows: one on the left and one on the right.
3462 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3463 * Stylus down on the left window, and then touch down on the right window.
3464 * Check that the right window doesn't get touches while the stylus is down on the left window.
3465 */
3466TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3468 sp<FakeWindowHandle> leftWindow =
3469 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3470 ADISPLAY_ID_DEFAULT);
3471 leftWindow->setFrame(Rect(0, 0, 100, 100));
3472
3473 sp<FakeWindowHandle> sbtRightWindow =
3474 sp<FakeWindowHandle>::make(application, mDispatcher,
3475 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3476 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3477 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3478
3479 mDispatcher->onWindowInfosChanged(
3480 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3481
3482 const int32_t stylusDeviceId = 5;
3483 const int32_t touchDeviceId = 4;
3484
3485 // Stylus down in the left window
3486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3487 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3488 .deviceId(stylusDeviceId)
3489 .build());
3490 leftWindow->consumeMotionEvent(
3491 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3492
3493 // Finger tap on the right window
3494 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3495 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3496 .deviceId(touchDeviceId)
3497 .build());
3498 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3499 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3500 .deviceId(touchDeviceId)
3501 .build());
3502
3503 // The touch should be blocked, because stylus is down somewhere else on screen!
3504 sbtRightWindow->assertNoEvents();
3505
3506 // Continue stylus motion, and ensure it's not impacted.
3507 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3508 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3509 .deviceId(stylusDeviceId)
3510 .build());
3511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3512 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3513 .deviceId(stylusDeviceId)
3514 .build());
3515 leftWindow->consumeMotionEvent(
3516 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3517 leftWindow->consumeMotionEvent(
3518 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3519
3520 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3522 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3523 .deviceId(touchDeviceId)
3524 .build());
3525 sbtRightWindow->consumeMotionEvent(
3526 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3527}
3528
3529/**
3530 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3531 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3532 *
3533 * Two windows: one on the left and one on the right.
3534 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3535 * Stylus hover on the left window, and then touch down on the right window.
3536 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3537 */
3538TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3539 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3540 sp<FakeWindowHandle> leftWindow =
3541 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3542 ADISPLAY_ID_DEFAULT);
3543 leftWindow->setFrame(Rect(0, 0, 100, 100));
3544
3545 sp<FakeWindowHandle> sbtRightWindow =
3546 sp<FakeWindowHandle>::make(application, mDispatcher,
3547 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3548 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3549 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3550
3551 mDispatcher->onWindowInfosChanged(
3552 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3553
3554 const int32_t stylusDeviceId = 5;
3555 const int32_t touchDeviceId = 4;
3556
3557 // Stylus hover in the left window
3558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3560 .deviceId(stylusDeviceId)
3561 .build());
3562 leftWindow->consumeMotionEvent(
3563 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3564
3565 // Finger tap on the right window
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3567 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3568 .deviceId(touchDeviceId)
3569 .build());
3570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3571 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3572 .deviceId(touchDeviceId)
3573 .build());
3574
3575 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3576 sbtRightWindow->assertNoEvents();
3577
3578 // Continue stylus motion, and ensure it's not impacted.
3579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3580 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3581 .deviceId(stylusDeviceId)
3582 .build());
3583 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3585 .deviceId(stylusDeviceId)
3586 .build());
3587 leftWindow->consumeMotionEvent(
3588 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3589 leftWindow->consumeMotionEvent(
3590 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3591
3592 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3594 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3595 .deviceId(touchDeviceId)
3596 .build());
3597 sbtRightWindow->consumeMotionEvent(
3598 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3599}
3600
3601/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003602 * A spy window above a window with no input channel.
3603 * Start hovering with a stylus device, and then tap with it.
3604 * Ensure spy window receives the entire sequence.
3605 */
3606TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3608 sp<FakeWindowHandle> spyWindow =
3609 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3610 spyWindow->setFrame(Rect(0, 0, 200, 200));
3611 spyWindow->setTrustedOverlay(true);
3612 spyWindow->setSpy(true);
3613 sp<FakeWindowHandle> window =
3614 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3615 window->setNoInputChannel(true);
3616 window->setFrame(Rect(0, 0, 200, 200));
3617
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003618 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003619
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003620 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3623 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003624 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3625 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3627 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3628 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003629 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3630
3631 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3633 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3634 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003635 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3636
3637 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003638 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3639 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3640 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003641 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3642
3643 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3645 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3646 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003647 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3648 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3650 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3651 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003652 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3653
3654 // No more events
3655 spyWindow->assertNoEvents();
3656 window->assertNoEvents();
3657}
3658
3659/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003660 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3661 * rejected. But since we already have an ongoing gesture, this event should be processed.
3662 * This prevents inconsistent events being handled inside the dispatcher.
3663 */
3664TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3666
3667 sp<FakeWindowHandle> window =
3668 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3669 window->setFrame(Rect(0, 0, 200, 200));
3670
3671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3672
3673 // Start hovering with stylus
3674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3676 .build());
3677 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3678
3679 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3680 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3681 .build();
3682 // Make this 'hoverExit' event stale
3683 mFakePolicy->setStaleEventTimeout(100ms);
3684 std::this_thread::sleep_for(100ms);
3685
3686 // It shouldn't be dropped by the dispatcher, even though it's stale.
3687 mDispatcher->notifyMotion(hoverExit);
3688 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3689
3690 // Stylus starts hovering again! There should be no crash.
3691 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3692 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3693 .build());
3694 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3695}
3696
3697/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003698 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3699 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3700 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3701 * While the mouse is down, new move events from the touch device should be ignored.
3702 */
3703TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3705 sp<FakeWindowHandle> spyWindow =
3706 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3707 spyWindow->setFrame(Rect(0, 0, 200, 200));
3708 spyWindow->setTrustedOverlay(true);
3709 spyWindow->setSpy(true);
3710 sp<FakeWindowHandle> window =
3711 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3712 window->setFrame(Rect(0, 0, 200, 200));
3713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003714 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003715
3716 const int32_t mouseDeviceId = 7;
3717 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003718
3719 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3721 .deviceId(mouseDeviceId)
3722 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3723 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003724 spyWindow->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3726 window->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3728
3729 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3731 .deviceId(touchDeviceId)
3732 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3733 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003734 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3735 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3736 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3737 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3738
Prabir Pradhan678438e2023-04-13 19:32:51 +00003739 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3740 .deviceId(touchDeviceId)
3741 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3742 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003743 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3744 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3745
3746 // Pilfer the stream
3747 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3748 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3749
Prabir Pradhan678438e2023-04-13 19:32:51 +00003750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3751 .deviceId(touchDeviceId)
3752 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3753 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3755
3756 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3758 .deviceId(mouseDeviceId)
3759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3761 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003762
3763 spyWindow->consumeMotionEvent(
3764 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3765 spyWindow->consumeMotionEvent(
3766 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3767 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3768
Prabir Pradhan678438e2023-04-13 19:32:51 +00003769 mDispatcher->notifyMotion(
3770 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3771 .deviceId(mouseDeviceId)
3772 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3773 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3774 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3775 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003776 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3777 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3778
3779 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3781 .deviceId(mouseDeviceId)
3782 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3784 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003785 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3786 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3787
3788 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3790 .deviceId(touchDeviceId)
3791 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3792 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003793
3794 // No more events
3795 spyWindow->assertNoEvents();
3796 window->assertNoEvents();
3797}
3798
3799/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003800 * On the display, have a single window, and also an area where there's no window.
3801 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3802 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3803 */
3804TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3806 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003807 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003808
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003809 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003810
3811 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003812 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003813
3814 mDispatcher->waitForIdle();
3815 window->assertNoEvents();
3816
3817 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003818 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003819 mDispatcher->waitForIdle();
3820 window->consumeMotionDown();
3821}
3822
3823/**
3824 * Same test as above, but instead of touching the empty space, the first touch goes to
3825 * non-touchable window.
3826 */
3827TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3829 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003830 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003831 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3832 window1->setTouchable(false);
3833 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003834 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003835 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003837 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003838
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003839 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003840 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003841
3842 mDispatcher->waitForIdle();
3843 window1->assertNoEvents();
3844 window2->assertNoEvents();
3845
3846 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003847 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003848 mDispatcher->waitForIdle();
3849 window2->consumeMotionDown();
3850}
3851
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003852/**
3853 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3854 * to the event time of the first ACTION_DOWN sent to the particular window.
3855 */
3856TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3857 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3858 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003859 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003860 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3861 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003862 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003863 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003865 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003866
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003868 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003869 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003870
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003871 const std::unique_ptr<MotionEvent> firstDown =
3872 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3873 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003874 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003875
3876 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003877 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003878 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003879
3880 const std::unique_ptr<MotionEvent> secondDown =
3881 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3882 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3883 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3884 // We currently send MOVE events to all windows receiving a split touch when there is any change
3885 // in the touch state, even when none of the pointers in the split window actually moved.
3886 // Document this behavior in the test.
3887 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003888
3889 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003890 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003891 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003892
3893 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3894 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003895
3896 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003897 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003898 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003899
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003900 window2->consumeMotionEvent(
3901 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3902 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003903
3904 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003905 mDispatcher->notifyMotion(
3906 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003907 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003908
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003909 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3910 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3911
3912 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003913 mDispatcher->notifyMotion(
3914 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003915 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003916
3917 window1->consumeMotionEvent(
3918 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3919 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003920}
3921
Garfield Tandf26e862020-07-01 20:18:19 -07003922TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003924 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003925 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003926 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003927 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003928 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003929 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003930
3931 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3932
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003933 mDispatcher->onWindowInfosChanged(
3934 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003935
3936 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003938 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003939 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3940 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003942 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003943 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003944
3945 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003947 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003948 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3949 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003951 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003952 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3953 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003954
3955 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003957 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003958 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3959 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003960 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003961 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003962 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3963 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003964
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003966 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003967 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3968 AINPUT_SOURCE_MOUSE)
3969 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3970 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003971 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003972 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003973 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003974
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003976 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003977 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3978 AINPUT_SOURCE_MOUSE)
3979 .buttonState(0)
3980 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003981 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003982 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003983 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003984
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003986 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003987 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3988 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003989 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003990 .build()));
3991 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3992
3993 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003995 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003996 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3997 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003998 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003999 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004000 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004001
4002 // No more events
4003 windowLeft->assertNoEvents();
4004 windowRight->assertNoEvents();
4005}
4006
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004007/**
4008 * Put two fingers down (and don't release them) and click the mouse button.
4009 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4010 * currently active gesture should be canceled, and the new one should proceed.
4011 */
4012TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4014 sp<FakeWindowHandle> window =
4015 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4016 window->setFrame(Rect(0, 0, 600, 800));
4017
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004018 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004019
4020 const int32_t touchDeviceId = 4;
4021 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004022
4023 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004024 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4025 .deviceId(touchDeviceId)
4026 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4027 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004028
Prabir Pradhan678438e2023-04-13 19:32:51 +00004029 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4030 .deviceId(touchDeviceId)
4031 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4032 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4033 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004034 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4035 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4036
4037 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4039 .deviceId(mouseDeviceId)
4040 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4041 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4042 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004043 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4044 WithPointerCount(2u)));
4045 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4046
Prabir Pradhan678438e2023-04-13 19:32:51 +00004047 mDispatcher->notifyMotion(
4048 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4049 .deviceId(mouseDeviceId)
4050 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4051 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4052 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4053 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004054 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4055
4056 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4057 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4059 .deviceId(touchDeviceId)
4060 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4061 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4062 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004063 window->assertNoEvents();
4064}
4065
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004066TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4068
4069 sp<FakeWindowHandle> spyWindow =
4070 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4071 spyWindow->setFrame(Rect(0, 0, 600, 800));
4072 spyWindow->setTrustedOverlay(true);
4073 spyWindow->setSpy(true);
4074 sp<FakeWindowHandle> window =
4075 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4076 window->setFrame(Rect(0, 0, 600, 800));
4077
4078 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004079 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004080
4081 // Send mouse cursor to the window
4082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004083 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004084 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4085 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004086 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004087 .build()));
4088
4089 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4090 WithSource(AINPUT_SOURCE_MOUSE)));
4091 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4092 WithSource(AINPUT_SOURCE_MOUSE)));
4093
4094 window->assertNoEvents();
4095 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004096}
4097
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004098TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4099 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4100
4101 sp<FakeWindowHandle> spyWindow =
4102 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4103 spyWindow->setFrame(Rect(0, 0, 600, 800));
4104 spyWindow->setTrustedOverlay(true);
4105 spyWindow->setSpy(true);
4106 sp<FakeWindowHandle> window =
4107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4108 window->setFrame(Rect(0, 0, 600, 800));
4109
4110 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004111 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004112
4113 // Send mouse cursor to the window
4114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004116 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4117 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004118 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004119 .build()));
4120
4121 // Move mouse cursor
4122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004123 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004124 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4125 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004127 .build()));
4128
4129 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4130 WithSource(AINPUT_SOURCE_MOUSE)));
4131 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4132 WithSource(AINPUT_SOURCE_MOUSE)));
4133 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4134 WithSource(AINPUT_SOURCE_MOUSE)));
4135 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4136 WithSource(AINPUT_SOURCE_MOUSE)));
4137 // Touch down on the window
4138 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004139 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004140 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4141 AINPUT_SOURCE_TOUCHSCREEN)
4142 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004144 .build()));
4145 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4146 WithSource(AINPUT_SOURCE_MOUSE)));
4147 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4148 WithSource(AINPUT_SOURCE_MOUSE)));
4149 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4150 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4151 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4152 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4153
4154 // pilfer the motion, retaining the gesture on the spy window.
4155 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4156 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4157 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4158
4159 // Touch UP on the window
4160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004161 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004162 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4163 AINPUT_SOURCE_TOUCHSCREEN)
4164 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004165 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004166 .build()));
4167 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4168 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4169
4170 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4171 // to send a new gesture. It should again go to both windows (spy and the window below), just
4172 // like the first gesture did, before pilfering. The window configuration has not changed.
4173
4174 // One more tap - DOWN
4175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004176 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004177 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4178 AINPUT_SOURCE_TOUCHSCREEN)
4179 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004180 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004181 .build()));
4182 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4183 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4184 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4185 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4186
4187 // Touch UP on the window
4188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004189 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004190 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4191 AINPUT_SOURCE_TOUCHSCREEN)
4192 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004193 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004194 .build()));
4195 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4196 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4197 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4198 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4199
4200 window->assertNoEvents();
4201 spyWindow->assertNoEvents();
4202}
4203
Garfield Tandf26e862020-07-01 20:18:19 -07004204// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4205// directly in this test.
4206TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004208 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004209 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004210 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004211
4212 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4213
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004214 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004215
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004217 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004218 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4219 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004220 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004221 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004222 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004223 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004225 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004226 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4227 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004228 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004229 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004230 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4231 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004232
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004234 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004235 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4236 AINPUT_SOURCE_MOUSE)
4237 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4238 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004239 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004240 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004241 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004242
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004244 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004245 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4246 AINPUT_SOURCE_MOUSE)
4247 .buttonState(0)
4248 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004249 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004250 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004251 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004252
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004254 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004255 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4256 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004257 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004258 .build()));
4259 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4260
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004261 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4262 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4263 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004264 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004265 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4266 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004267 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004268 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004269 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004270}
4271
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004272/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004273 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4274 * is generated.
4275 */
4276TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4278 sp<FakeWindowHandle> window =
4279 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4280 window->setFrame(Rect(0, 0, 1200, 800));
4281
4282 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4283
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004285
4286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004287 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004288 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4289 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004290 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004291 .build()));
4292 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4293
4294 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004295 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004296 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4297}
4298
4299/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004300 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4301 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004302TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4303 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4304 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004305 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4306 sp<FakeWindowHandle> window =
4307 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4308 window->setFrame(Rect(0, 0, 1200, 800));
4309
4310 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4311
4312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4313
4314 MotionEventBuilder hoverEnterBuilder =
4315 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4316 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4317 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4319 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4321 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4322 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4323 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4324}
4325
4326/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004327 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4328 */
4329TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4330 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4331 sp<FakeWindowHandle> window =
4332 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4333 window->setFrame(Rect(0, 0, 100, 100));
4334
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004335 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004336
4337 const int32_t mouseDeviceId = 7;
4338 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004339
4340 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4342 .deviceId(mouseDeviceId)
4343 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4344 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004345 window->consumeMotionEvent(
4346 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4347
4348 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004349 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4350 .deviceId(touchDeviceId)
4351 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4352 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004353
4354 window->consumeMotionEvent(
4355 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4356 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4357}
4358
4359/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004360 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004361 * The tap causes a HOVER_EXIT event to be generated because the current event
4362 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004363 */
4364TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4365 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4366 sp<FakeWindowHandle> window =
4367 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4368 window->setFrame(Rect(0, 0, 100, 100));
4369
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004370 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4372 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4373 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004374 ASSERT_NO_FATAL_FAILURE(
4375 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4376 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004377
4378 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004379 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4380 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4381 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004382 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004383 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4384 WithSource(AINPUT_SOURCE_MOUSE))));
4385
4386 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004387 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4388 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4389
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4391 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4392 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004393 ASSERT_NO_FATAL_FAILURE(
4394 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4395 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4396}
4397
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004398TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4400 sp<FakeWindowHandle> windowDefaultDisplay =
4401 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4402 ADISPLAY_ID_DEFAULT);
4403 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4404 sp<FakeWindowHandle> windowSecondDisplay =
4405 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4406 SECOND_DISPLAY_ID);
4407 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4408
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004409 mDispatcher->onWindowInfosChanged(
4410 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004411
4412 // Set cursor position in window in default display and check that hover enter and move
4413 // events are generated.
4414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004415 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004416 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4417 AINPUT_SOURCE_MOUSE)
4418 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004420 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004421 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004422
4423 // Remove all windows in secondary display and check that no event happens on window in
4424 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004425 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4426
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004427 windowDefaultDisplay->assertNoEvents();
4428
4429 // Move cursor position in window in default display and check that only hover move
4430 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004431 mDispatcher->onWindowInfosChanged(
4432 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004434 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004435 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4436 AINPUT_SOURCE_MOUSE)
4437 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004438 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004439 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004440 windowDefaultDisplay->consumeMotionEvent(
4441 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4442 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004443 windowDefaultDisplay->assertNoEvents();
4444}
4445
Garfield Tan00f511d2019-06-12 16:55:40 -07004446TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004448
4449 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004450 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004451 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004452 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004453 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004454 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004455
4456 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4457
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004458 mDispatcher->onWindowInfosChanged(
4459 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004460
4461 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4462 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004464 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004465 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004466 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004467 windowRight->assertNoEvents();
4468}
4469
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004470TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004471 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004472 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4473 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004474 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004475
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004476 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004477 setFocusedWindow(window);
4478
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004479 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004480
Prabir Pradhan678438e2023-04-13 19:32:51 +00004481 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004482
4483 // Window should receive key down event.
4484 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4485
4486 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4487 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004488 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004489 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004490}
4491
4492TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004493 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004494 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4495 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004496
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004498
Prabir Pradhan678438e2023-04-13 19:32:51 +00004499 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4500 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004501
4502 // Window should receive motion down event.
4503 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4504
4505 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4506 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004507 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004508 window->consumeMotionEvent(
4509 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004510}
4511
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004512TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4513 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4514 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4515 "Fake Window", ADISPLAY_ID_DEFAULT);
4516
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004518
4519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4520 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4521 .build());
4522
4523 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4524
4525 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4526 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4527 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4528
4529 // After the device has been reset, a new hovering stream can be sent to the window
4530 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4531 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4532 .build());
4533 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4534}
4535
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004536TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4537 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004538 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4539 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004540 window->setFocusable(true);
4541
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004542 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004543 setFocusedWindow(window);
4544
4545 window->consumeFocusEvent(true);
4546
Prabir Pradhan678438e2023-04-13 19:32:51 +00004547 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004548 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4549 const nsecs_t injectTime = keyArgs.eventTime;
4550 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004551 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004552 // The dispatching time should be always greater than or equal to intercept key timeout.
4553 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4554 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4555 std::chrono::nanoseconds(interceptKeyTimeout).count());
4556}
4557
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004558/**
4559 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4560 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004561TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4562 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004563 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4564 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004565 window->setFocusable(true);
4566
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004567 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004568 setFocusedWindow(window);
4569
4570 window->consumeFocusEvent(true);
4571
Prabir Pradhan678438e2023-04-13 19:32:51 +00004572 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004573 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004574
4575 // Set a value that's significantly larger than the default consumption timeout. If the
4576 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4577 mFakePolicy->setInterceptKeyTimeout(600ms);
4578 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4579 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004580 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4581}
4582
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004583/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004584 * Two windows. First is a regular window. Second does not overlap with the first, and has
4585 * WATCH_OUTSIDE_TOUCH.
4586 * Both windows are owned by the same UID.
4587 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4588 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4589 */
4590TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4591 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004592 sp<FakeWindowHandle> window =
4593 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004594 window->setFrame(Rect{0, 0, 100, 100});
4595
4596 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004597 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004598 ADISPLAY_ID_DEFAULT);
4599 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4600 outsideWindow->setWatchOutsideTouch(true);
4601 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004602 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004603
4604 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004605 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4606 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4607 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004608 window->consumeMotionDown();
4609 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4610 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4611 outsideWindow->consumeMotionEvent(
4612 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004613
4614 // Ensure outsideWindow doesn't get any more events for the gesture.
4615 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4616 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4617 window->consumeMotionMove();
4618 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004619}
4620
4621/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004622 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4623 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4624 * ACTION_OUTSIDE event is sent per gesture.
4625 */
4626TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4627 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004629 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4630 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004631 window->setWatchOutsideTouch(true);
4632 window->setFrame(Rect{0, 0, 100, 100});
4633 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004634 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4635 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004636 secondWindow->setFrame(Rect{100, 100, 200, 200});
4637 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004638 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4639 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004640 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004641 mDispatcher->onWindowInfosChanged(
4642 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004643
4644 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004645 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4646 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4647 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004648 window->assertNoEvents();
4649 secondWindow->assertNoEvents();
4650
4651 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4652 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004653 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4654 ADISPLAY_ID_DEFAULT,
4655 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004656 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4657 window->consumeMotionEvent(
4658 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004659 secondWindow->consumeMotionDown();
4660 thirdWindow->assertNoEvents();
4661
4662 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4663 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004664 mDispatcher->notifyMotion(
4665 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4666 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004667 window->assertNoEvents();
4668 secondWindow->consumeMotionMove();
4669 thirdWindow->consumeMotionDown();
4670}
4671
Prabir Pradhan814fe082022-07-22 20:22:18 +00004672TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4673 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004674 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4675 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004676 window->setFocusable(true);
4677
Patrick Williamsd828f302023-04-28 17:52:08 -05004678 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004679 setFocusedWindow(window);
4680
4681 window->consumeFocusEvent(true);
4682
Prabir Pradhan678438e2023-04-13 19:32:51 +00004683 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4684 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4685 mDispatcher->notifyKey(keyDown);
4686 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004687
4688 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4689 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4690
4691 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004692 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004693
4694 window->consumeFocusEvent(false);
4695
Prabir Pradhan678438e2023-04-13 19:32:51 +00004696 mDispatcher->notifyKey(keyDown);
4697 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004698 window->assertNoEvents();
4699}
4700
Arthur Hung96483742022-11-15 03:30:48 +00004701TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4703 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4704 "Fake Window", ADISPLAY_ID_DEFAULT);
4705 // Ensure window is non-split and have some transform.
4706 window->setPreventSplitting(true);
4707 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004708 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004709
4710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004712 {50, 50}))
4713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4714 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4715
4716 const MotionEvent secondFingerDownEvent =
4717 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4718 .displayId(ADISPLAY_ID_DEFAULT)
4719 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004720 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4721 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004722 .build();
4723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004724 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004725 InputEventInjectionSync::WAIT_FOR_RESULT))
4726 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4727
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004728 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4729 ASSERT_NE(nullptr, event);
4730 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4731 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4732 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4733 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4734 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004735}
4736
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004737/**
4738 * Two windows: a splittable and a non-splittable.
4739 * The non-splittable window shouldn't receive any "incomplete" gestures.
4740 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4741 * The second pointer should be dropped because the initial window is splittable, so it won't get
4742 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4743 * "incomplete" gestures.
4744 */
4745TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4747 sp<FakeWindowHandle> leftWindow =
4748 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4749 ADISPLAY_ID_DEFAULT);
4750 leftWindow->setPreventSplitting(false);
4751 leftWindow->setFrame(Rect(0, 0, 100, 100));
4752 sp<FakeWindowHandle> rightWindow =
4753 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4754 ADISPLAY_ID_DEFAULT);
4755 rightWindow->setPreventSplitting(true);
4756 rightWindow->setFrame(Rect(100, 100, 200, 200));
4757 mDispatcher->onWindowInfosChanged(
4758 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4759
4760 // Touch down on left, splittable window
4761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4762 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4763 .build());
4764 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4765
4766 mDispatcher->notifyMotion(
4767 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4768 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4769 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4770 .build());
4771 leftWindow->assertNoEvents();
4772 rightWindow->assertNoEvents();
4773}
4774
Harry Cuttsb166c002023-05-09 13:06:05 +00004775TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4777 sp<FakeWindowHandle> window =
4778 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4779 window->setFrame(Rect(0, 0, 400, 400));
4780 sp<FakeWindowHandle> trustedOverlay =
4781 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4782 ADISPLAY_ID_DEFAULT);
4783 trustedOverlay->setSpy(true);
4784 trustedOverlay->setTrustedOverlay(true);
4785
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004786 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004787
4788 // Start a three-finger touchpad swipe
4789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4790 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4791 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4792 .build());
4793 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4794 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4795 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4796 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4797 .build());
4798 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4799 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4800 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4801 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4802 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4803 .build());
4804
4805 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4806 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4807 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4808
4809 // Move the swipe a bit
4810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4811 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4812 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4813 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4814 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4815 .build());
4816
4817 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4818
4819 // End the swipe
4820 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4821 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4822 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4823 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4824 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4825 .build());
4826 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4827 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4828 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4829 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4830 .build());
4831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4832 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4833 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4834 .build());
4835
4836 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4837 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4838 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4839
4840 window->assertNoEvents();
4841}
4842
4843TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4845 sp<FakeWindowHandle> window =
4846 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4847 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004849
4850 // Start a three-finger touchpad swipe
4851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4852 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4853 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4854 .build());
4855 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4856 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4857 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4858 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4859 .build());
4860 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4861 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4862 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4863 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4864 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4865 .build());
4866
4867 // Move the swipe a bit
4868 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4869 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4870 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4871 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4872 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4873 .build());
4874
4875 // End the swipe
4876 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4877 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4878 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4879 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4880 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4881 .build());
4882 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4883 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4884 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4885 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4886 .build());
4887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4888 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4889 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4890 .build());
4891
4892 window->assertNoEvents();
4893}
4894
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004895/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004896 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4897 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004898 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004899 */
4900TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4902 sp<FakeWindowHandle> window =
4903 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4904 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004905 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004906
4907 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4908 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4909 .downTime(baseTime + 10)
4910 .eventTime(baseTime + 10)
4911 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4912 .build());
4913
4914 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4915
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004916 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004917 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004918
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004919 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004920
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004921 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4922 .downTime(baseTime + 10)
4923 .eventTime(baseTime + 30)
4924 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4925 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4926 .build());
4927
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004928 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4929
4930 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004931 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4932 .downTime(baseTime + 10)
4933 .eventTime(baseTime + 40)
4934 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4935 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4936 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004937
4938 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4939
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004940 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4941 .downTime(baseTime + 10)
4942 .eventTime(baseTime + 50)
4943 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4944 .build());
4945
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004946 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4947
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4949 .downTime(baseTime + 60)
4950 .eventTime(baseTime + 60)
4951 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4952 .build());
4953
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004954 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004955}
4956
4957/**
Hu Guo771a7692023-09-17 20:51:08 +08004958 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4959 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4960 * its coordinates should be converted by the transform of the windows of target screen.
4961 */
4962TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4963 // This case will create a window and a spy window on the default display and mirror
4964 // window on the second display. cancel event is sent through spy window pilferPointers
4965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4966
4967 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4968 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4969 spyWindowDefaultDisplay->setTrustedOverlay(true);
4970 spyWindowDefaultDisplay->setSpy(true);
4971
4972 sp<FakeWindowHandle> windowDefaultDisplay =
4973 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4974 ADISPLAY_ID_DEFAULT);
4975 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4976
4977 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4978 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4979
4980 // Add the windows to the dispatcher
4981 mDispatcher->onWindowInfosChanged(
4982 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4983 *windowSecondDisplay->getInfo()},
4984 {},
4985 0,
4986 0});
4987
4988 // Send down to ADISPLAY_ID_DEFAULT
4989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4990 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4991 {100, 100}))
4992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4993
4994 spyWindowDefaultDisplay->consumeMotionDown();
4995 windowDefaultDisplay->consumeMotionDown();
4996
4997 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4998
4999 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005000 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5001 ASSERT_NE(nullptr, event);
5002 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005003
5004 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
5005 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
5006 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
5007 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005008 EXPECT_EQ(100, event->getX(0));
5009 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005010}
5011
5012/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005013 * Ensure the correct coordinate spaces are used by InputDispatcher.
5014 *
5015 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5016 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5017 * space.
5018 */
5019class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5020public:
5021 void SetUp() override {
5022 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005023 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005024 }
5025
5026 void addDisplayInfo(int displayId, const ui::Transform& transform) {
5027 gui::DisplayInfo info;
5028 info.displayId = displayId;
5029 info.transform = transform;
5030 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005031 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005032 }
5033
5034 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5035 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005036 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005037 }
5038
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005039 void removeAllWindowsAndDisplays() {
5040 mDisplayInfos.clear();
5041 mWindowInfos.clear();
5042 }
5043
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005044 // Set up a test scenario where the display has a scaled projection and there are two windows
5045 // on the display.
5046 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5047 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5048 // respectively.
5049 ui::Transform displayTransform;
5050 displayTransform.set(2, 0, 0, 4);
5051 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5052
5053 std::shared_ptr<FakeApplicationHandle> application =
5054 std::make_shared<FakeApplicationHandle>();
5055
5056 // Add two windows to the display. Their frames are represented in the display space.
5057 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005058 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5059 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005060 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5061 addWindow(firstWindow);
5062
5063 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005064 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5065 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005066 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5067 addWindow(secondWindow);
5068 return {std::move(firstWindow), std::move(secondWindow)};
5069 }
5070
5071private:
5072 std::vector<gui::DisplayInfo> mDisplayInfos;
5073 std::vector<gui::WindowInfo> mWindowInfos;
5074};
5075
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005076TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005077 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5078 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005079 // selected so that if the hit test was performed with the point and the bounds being in
5080 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005081 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5082 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5083 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005084
5085 firstWindow->consumeMotionDown();
5086 secondWindow->assertNoEvents();
5087}
5088
5089// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5090// the event should be treated as being in the logical display space.
5091TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5092 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5093 // Send down to the first window. The point is represented in the logical display space. The
5094 // point is selected so that if the hit test was done in logical display space, then it would
5095 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005096 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005097 PointF{75 * 2, 55 * 4});
5098
5099 firstWindow->consumeMotionDown();
5100 secondWindow->assertNoEvents();
5101}
5102
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005103// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5104// event should be treated as being in the logical display space.
5105TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5106 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5107
5108 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5109 ui::Transform injectedEventTransform;
5110 injectedEventTransform.set(matrix);
5111 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5112 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5113
5114 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5115 .displayId(ADISPLAY_ID_DEFAULT)
5116 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005117 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005118 .x(untransformedPoint.x)
5119 .y(untransformedPoint.y))
5120 .build();
5121 event.transform(matrix);
5122
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005123 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005124 InputEventInjectionSync::WAIT_FOR_RESULT);
5125
5126 firstWindow->consumeMotionDown();
5127 secondWindow->assertNoEvents();
5128}
5129
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005130TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5131 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5132
5133 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005134 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5135 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5136 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005137
5138 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005139 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5140 ASSERT_NE(nullptr, event);
5141 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005142
5143 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005144 EXPECT_EQ(300, event->getRawX(0));
5145 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005146
5147 // Ensure that the x and y values are in the window's coordinate space.
5148 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5149 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005150 EXPECT_EQ(100, event->getX(0));
5151 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005152}
5153
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005154TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5155 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5156 // The monitor will always receive events in the logical display's coordinate space, because
5157 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005158 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005159
5160 // Send down to the first window.
5161 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5162 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5163 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5164 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5165
5166 // Second pointer goes down on second window.
5167 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5168 ADISPLAY_ID_DEFAULT,
5169 {PointF{50, 100}, PointF{150, 220}}));
5170 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5171 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5172 {1, PointF{300, 880}}};
5173 monitor.consumeMotionEvent(
5174 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5175
5176 mDispatcher->cancelCurrentTouch();
5177
5178 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5179 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5180 monitor.consumeMotionEvent(
5181 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5182}
5183
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005184TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5185 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5186
5187 // Send down to the first window.
5188 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5189 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5190 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5191
5192 // The pointer is transferred to the second window, and the second window receives it in the
5193 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005194 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005195 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5196 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5197}
5198
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005199TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5200 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5201
5202 // Send hover move to the second window, and ensure it shows up as hover enter.
5203 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5204 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5205 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5206 WithCoords(100, 80), WithRawCoords(300, 880)));
5207
5208 // Touch down at the same location and ensure a hover exit is synthesized.
5209 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5210 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5211 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5212 WithRawCoords(300, 880)));
5213 secondWindow->consumeMotionEvent(
5214 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5215 secondWindow->assertNoEvents();
5216 firstWindow->assertNoEvents();
5217}
5218
Prabir Pradhan453ae732023-10-13 14:30:14 +00005219// Same as above, but while the window is being mirrored.
5220TEST_F(InputDispatcherDisplayProjectionTest,
5221 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5222 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5223
5224 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5225 ui::Transform secondDisplayTransform;
5226 secondDisplayTransform.set(matrix);
5227 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5228
5229 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5230 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5231 addWindow(secondWindowClone);
5232
5233 // Send hover move to the second window, and ensure it shows up as hover enter.
5234 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5235 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5236 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5237 WithCoords(100, 80), WithRawCoords(300, 880)));
5238
5239 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5240 // display.
5241 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5242 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5243 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5244 WithRawCoords(300, 880)));
5245 secondWindow->consumeMotionEvent(
5246 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5247 secondWindow->assertNoEvents();
5248 firstWindow->assertNoEvents();
5249}
5250
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005251TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5252 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5253
5254 // Send hover enter to second window
5255 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5256 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5257 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5258 WithCoords(100, 80), WithRawCoords(300, 880)));
5259
5260 mDispatcher->cancelCurrentTouch();
5261
5262 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5263 WithRawCoords(300, 880)));
5264 secondWindow->assertNoEvents();
5265 firstWindow->assertNoEvents();
5266}
5267
Prabir Pradhan453ae732023-10-13 14:30:14 +00005268// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005269TEST_F(InputDispatcherDisplayProjectionTest,
5270 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5271 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5272
5273 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5274 ui::Transform secondDisplayTransform;
5275 secondDisplayTransform.set(matrix);
5276 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5277
5278 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5279 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5280 addWindow(secondWindowClone);
5281
5282 // Send hover enter to second window
5283 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5284 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5285 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5286 WithCoords(100, 80), WithRawCoords(300, 880),
5287 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5288
5289 mDispatcher->cancelCurrentTouch();
5290
5291 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5292 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5293 WithRawCoords(300, 880),
5294 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5295 secondWindow->assertNoEvents();
5296 firstWindow->assertNoEvents();
5297}
5298
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005299/** Ensure consistent behavior of InputDispatcher in all orientations. */
5300class InputDispatcherDisplayOrientationFixture
5301 : public InputDispatcherDisplayProjectionTest,
5302 public ::testing::WithParamInterface<ui::Rotation> {};
5303
5304// This test verifies the touchable region of a window for all rotations of the display by tapping
5305// in different locations on the display, specifically points close to the four corners of a
5306// window.
5307TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5308 constexpr static int32_t displayWidth = 400;
5309 constexpr static int32_t displayHeight = 800;
5310
5311 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5312
5313 const auto rotation = GetParam();
5314
5315 // Set up the display with the specified rotation.
5316 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5317 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5318 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5319 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5320 logicalDisplayWidth, logicalDisplayHeight);
5321 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5322
5323 // Create a window with its bounds determined in the logical display.
5324 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5325 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5326 sp<FakeWindowHandle> window =
5327 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5328 window->setFrame(frameInDisplay, displayTransform);
5329 addWindow(window);
5330
5331 // The following points in logical display space should be inside the window.
5332 static const std::array<vec2, 4> insidePoints{
5333 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5334 for (const auto pointInsideWindow : insidePoints) {
5335 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5336 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005337 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5338 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5339 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005340 window->consumeMotionDown();
5341
Prabir Pradhan678438e2023-04-13 19:32:51 +00005342 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5343 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5344 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005345 window->consumeMotionUp();
5346 }
5347
5348 // The following points in logical display space should be outside the window.
5349 static const std::array<vec2, 5> outsidePoints{
5350 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5351 for (const auto pointOutsideWindow : outsidePoints) {
5352 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5353 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005354 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5355 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5356 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005357
Prabir Pradhan678438e2023-04-13 19:32:51 +00005358 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5359 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5360 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005361 }
5362 window->assertNoEvents();
5363}
5364
5365// Run the precision tests for all rotations.
5366INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5367 InputDispatcherDisplayOrientationFixture,
5368 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5369 ui::ROTATION_270),
5370 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5371 return ftl::enum_string(testParamInfo.param);
5372 });
5373
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005374using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5375 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005376
5377class TransferTouchFixture : public InputDispatcherTest,
5378 public ::testing::WithParamInterface<TransferFunction> {};
5379
5380TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005382
5383 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005384 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005385 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5386 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005387 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005388 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005389 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5390 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005391 sp<FakeWindowHandle> wallpaper =
5392 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5393 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005394 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005395 mDispatcher->onWindowInfosChanged(
5396 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00005397 setFocusedWindow(firstWindow);
5398 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005399
5400 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005401 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5402 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005403
Svet Ganov5d3bc372020-01-26 23:11:07 -08005404 // Only the first window should get the down event
5405 firstWindow->consumeMotionDown();
5406 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005407 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005408 // Dispatcher reports pointer down outside focus for the wallpaper
5409 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005410
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005411 // Transfer touch to the second window
5412 TransferFunction f = GetParam();
5413 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5414 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005415 // The first window gets cancel and the second gets down
5416 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005417 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005418 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005419 // There should not be any changes to the focused window when transferring touch
5420 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005421
5422 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005423 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5424 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005425 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005426 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005427 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005428 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005429}
5430
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005431/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005432 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5433 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5434 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005435 * natural to the user.
5436 * In this test, we are sending a pointer to both spy window and first window. We then try to
5437 * transfer touch to the second window. The dispatcher should identify the first window as the
5438 * one that should lose the gesture, and therefore the action should be to move the gesture from
5439 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005440 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5441 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005442 */
5443TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5444 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5445
5446 // Create a couple of windows + a spy window
5447 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005448 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005449 spyWindow->setTrustedOverlay(true);
5450 spyWindow->setSpy(true);
5451 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005452 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005453 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005454 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005455
5456 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005457 mDispatcher->onWindowInfosChanged(
5458 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005459
5460 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005461 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5462 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005463 // Only the first window and spy should get the down event
5464 spyWindow->consumeMotionDown();
5465 firstWindow->consumeMotionDown();
5466
5467 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005468 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005469 TransferFunction f = GetParam();
5470 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5471 ASSERT_TRUE(success);
5472 // The first window gets cancel and the second gets down
5473 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005474 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005475
5476 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005477 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5478 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005479 // The first window gets no events and the second+spy get up
5480 firstWindow->assertNoEvents();
5481 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005482 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005483}
5484
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005485TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005487
5488 PointF touchPoint = {10, 10};
5489
5490 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005491 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005492 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5493 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005494 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005495 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005496 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5497 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005498 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005499
5500 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005501 mDispatcher->onWindowInfosChanged(
5502 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005503
5504 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5506 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5507 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005508 // Only the first window should get the down event
5509 firstWindow->consumeMotionDown();
5510 secondWindow->assertNoEvents();
5511
5512 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005513 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5514 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005515 // Only the first window should get the pointer down event
5516 firstWindow->consumeMotionPointerDown(1);
5517 secondWindow->assertNoEvents();
5518
5519 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005520 TransferFunction f = GetParam();
5521 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5522 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005523 // The first window gets cancel and the second gets down and pointer down
5524 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005525 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5526 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5527 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005528
5529 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005530 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5531 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005532 // The first window gets nothing and the second gets pointer up
5533 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005534 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5535 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005536
5537 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005538 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5539 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005540 // The first window gets nothing and the second gets up
5541 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005542 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005543}
5544
Arthur Hungc539dbb2022-12-08 07:45:36 +00005545TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5546 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5547
5548 // Create a couple of windows
5549 sp<FakeWindowHandle> firstWindow =
5550 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5551 ADISPLAY_ID_DEFAULT);
5552 firstWindow->setDupTouchToWallpaper(true);
5553 sp<FakeWindowHandle> secondWindow =
5554 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5555 ADISPLAY_ID_DEFAULT);
5556 secondWindow->setDupTouchToWallpaper(true);
5557
5558 sp<FakeWindowHandle> wallpaper1 =
5559 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5560 wallpaper1->setIsWallpaper(true);
5561
5562 sp<FakeWindowHandle> wallpaper2 =
5563 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5564 wallpaper2->setIsWallpaper(true);
5565 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005566 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5567 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5568 {},
5569 0,
5570 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005571
5572 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005573 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5574 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005575
5576 // Only the first window should get the down event
5577 firstWindow->consumeMotionDown();
5578 secondWindow->assertNoEvents();
5579 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5580 wallpaper2->assertNoEvents();
5581
5582 // Transfer touch focus to the second window
5583 TransferFunction f = GetParam();
5584 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5585 ASSERT_TRUE(success);
5586
5587 // The first window gets cancel and the second gets down
5588 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005589 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005590 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005591 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5592 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005593
5594 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5596 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005597 // The first window gets no events and the second gets up
5598 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005599 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005600 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005601 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5602 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005603}
5604
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005605// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005606// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005607// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005608INSTANTIATE_TEST_SUITE_P(
5609 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5610 ::testing::Values(
5611 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5612 sp<IBinder> destChannelToken) {
5613 return dispatcher->transferTouchOnDisplay(destChannelToken,
5614 ADISPLAY_ID_DEFAULT);
5615 },
5616 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5617 sp<IBinder> to) {
5618 return dispatcher->transferTouchGesture(from, to,
5619 /*isDragAndDrop=*/false);
5620 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005621
Prabir Pradhan367f3432024-02-13 23:05:58 +00005622TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005624
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005625 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005626 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5627 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005628 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005629
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005630 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005631 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5632 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005633 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005634
5635 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005636 mDispatcher->onWindowInfosChanged(
5637 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005638
5639 PointF pointInFirst = {300, 200};
5640 PointF pointInSecond = {300, 600};
5641
5642 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005643 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5644 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5645 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005646 // Only the first window should get the down event
5647 firstWindow->consumeMotionDown();
5648 secondWindow->assertNoEvents();
5649
5650 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005651 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5652 ADISPLAY_ID_DEFAULT,
5653 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005654 // The first window gets a move and the second a down
5655 firstWindow->consumeMotionMove();
5656 secondWindow->consumeMotionDown();
5657
Prabir Pradhan367f3432024-02-13 23:05:58 +00005658 // Transfer touch to the second window
5659 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005660 // The first window gets cancel and the new gets pointer down (it already saw down)
5661 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005662 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5663 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005664
5665 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005666 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5667 ADISPLAY_ID_DEFAULT,
5668 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005669 // The first window gets nothing and the second gets pointer up
5670 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005671 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5672 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005673
5674 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005675 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5676 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005677 // The first window gets nothing and the second gets up
5678 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005679 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005680}
5681
Prabir Pradhan367f3432024-02-13 23:05:58 +00005682// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5683// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5684// receiving touch is not supported, so the touch should continue on those windows and the
5685// transferred-to window should get nothing.
5686TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005687 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5688
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005689 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005690 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5691 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005692 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005693
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005694 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005695 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5696 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005697 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005698
5699 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005700 mDispatcher->onWindowInfosChanged(
5701 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005702
5703 PointF pointInFirst = {300, 200};
5704 PointF pointInSecond = {300, 600};
5705
5706 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005707 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5708 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5709 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005710 // Only the first window should get the down event
5711 firstWindow->consumeMotionDown();
5712 secondWindow->assertNoEvents();
5713
5714 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005715 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5716 ADISPLAY_ID_DEFAULT,
5717 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005718 // The first window gets a move and the second a down
5719 firstWindow->consumeMotionMove();
5720 secondWindow->consumeMotionDown();
5721
5722 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005723 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005724 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5725 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005726 ASSERT_FALSE(transferred);
5727 firstWindow->assertNoEvents();
5728 secondWindow->assertNoEvents();
5729
5730 // The rest of the dispatch should proceed as normal
5731 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005732 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5733 ADISPLAY_ID_DEFAULT,
5734 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005735 // The first window gets MOVE and the second gets pointer up
5736 firstWindow->consumeMotionMove();
5737 secondWindow->consumeMotionUp();
5738
5739 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005740 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5741 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005742 // The first window gets nothing and the second gets up
5743 firstWindow->consumeMotionUp();
5744 secondWindow->assertNoEvents();
5745}
5746
Arthur Hungabbb9d82021-09-01 14:52:30 +00005747// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005748// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005749// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005750TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5752 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005753 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005754 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005755 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005756 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005757 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005758
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005759 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005760 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005761
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005762 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005763 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005764
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005765 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005766 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005767
5768 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005769 mDispatcher->onWindowInfosChanged(
5770 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5771 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5772 *secondWindowInPrimary->getInfo()},
5773 {},
5774 0,
5775 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005776
5777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005779 {50, 50}))
5780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5781
5782 // Window should receive motion event.
5783 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5784
Prabir Pradhan367f3432024-02-13 23:05:58 +00005785 // Transfer touch
5786 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5787 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005788 // The first window gets cancel.
5789 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005790 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5791 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005792
5793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005794 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005795 ADISPLAY_ID_DEFAULT, {150, 50}))
5796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5797 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005798 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5799 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005800
5801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005802 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005803 {150, 50}))
5804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5805 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005806 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005807}
5808
Prabir Pradhan367f3432024-02-13 23:05:58 +00005809// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5810// 'transferTouchOnDisplay' api.
5811TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5813 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005814 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005815 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005816 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005817 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005818 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005819
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005820 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005821 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005822
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005823 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005824 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005825
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005826 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005827 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005828
5829 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005830 mDispatcher->onWindowInfosChanged(
5831 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5832 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5833 *secondWindowInPrimary->getInfo()},
5834 {},
5835 0,
5836 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005837
5838 // Touch on second display.
5839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005840 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5841 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5843
5844 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005845 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005846
5847 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005848 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5849 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005850
5851 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005852 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005853 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5854 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005855
5856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005857 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005858 SECOND_DISPLAY_ID, {150, 50}))
5859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005860 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005861 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5862 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005863
5864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005865 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005867 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005868 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005869}
5870
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005871TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005873 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5874 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005875
Vishnu Nair47074b82020-08-14 11:54:47 -07005876 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005878 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005879
5880 window->consumeFocusEvent(true);
5881
Prabir Pradhan678438e2023-04-13 19:32:51 +00005882 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005883
5884 // Window should receive key down event.
5885 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005886
5887 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005888 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005889 mFakePolicy->assertUserActivityPoked();
5890}
5891
5892TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5894 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5895 "Fake Window", ADISPLAY_ID_DEFAULT);
5896
5897 window->setDisableUserActivity(true);
5898 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005899 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005900 setFocusedWindow(window);
5901
5902 window->consumeFocusEvent(true);
5903
5904 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5905
5906 // Window should receive key down event.
5907 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5908
5909 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005910 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005911 mFakePolicy->assertUserActivityNotPoked();
5912}
5913
5914TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5916 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5917 "Fake Window", ADISPLAY_ID_DEFAULT);
5918
5919 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005920 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005921 setFocusedWindow(window);
5922
5923 window->consumeFocusEvent(true);
5924
5925 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5926 mDispatcher->waitForIdle();
5927
5928 // System key is not passed down
5929 window->assertNoEvents();
5930
5931 // Should have poked user activity
5932 mFakePolicy->assertUserActivityPoked();
5933}
5934
5935TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5937 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5938 "Fake Window", ADISPLAY_ID_DEFAULT);
5939
5940 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005942 setFocusedWindow(window);
5943
5944 window->consumeFocusEvent(true);
5945
5946 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5947 mDispatcher->waitForIdle();
5948
5949 // System key is not passed down
5950 window->assertNoEvents();
5951
5952 // Should have poked user activity
5953 mFakePolicy->assertUserActivityPoked();
5954}
5955
5956TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5957 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5958 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5959 "Fake Window", ADISPLAY_ID_DEFAULT);
5960
5961 window->setDisableUserActivity(true);
5962 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005963 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005964 setFocusedWindow(window);
5965
5966 window->consumeFocusEvent(true);
5967
5968 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5969 mDispatcher->waitForIdle();
5970
5971 // System key is not passed down
5972 window->assertNoEvents();
5973
5974 // Should have poked user activity
5975 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005976}
5977
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005978TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5980 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5981 "Fake Window", ADISPLAY_ID_DEFAULT);
5982
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005983 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005984
5985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005986 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005987 ADISPLAY_ID_DEFAULT, {100, 100}))
5988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5989
5990 window->consumeMotionEvent(
5991 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5992
5993 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005994 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005995 mFakePolicy->assertUserActivityPoked();
5996}
5997
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005998TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005999 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006000 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6001 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006002
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006003 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006004
Prabir Pradhan678438e2023-04-13 19:32:51 +00006005 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006006 mDispatcher->waitForIdle();
6007
6008 window->assertNoEvents();
6009}
6010
6011// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6012TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006014 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6015 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006016
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006017 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006018
6019 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00006020 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006021 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006022 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6023 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006024
6025 // Window should receive only the motion event
6026 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6027 window->assertNoEvents(); // Key event or focus event will not be received
6028}
6029
arthurhungea3f4fc2020-12-21 23:18:53 +08006030TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6031 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6032
arthurhungea3f4fc2020-12-21 23:18:53 +08006033 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006034 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
6035 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006036 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006037
arthurhungea3f4fc2020-12-21 23:18:53 +08006038 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006039 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
6040 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006041 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006042
6043 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006044 mDispatcher->onWindowInfosChanged(
6045 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006046
6047 PointF pointInFirst = {300, 200};
6048 PointF pointInSecond = {300, 600};
6049
6050 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006051 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6052 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6053 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006054 // Only the first window should get the down event
6055 firstWindow->consumeMotionDown();
6056 secondWindow->assertNoEvents();
6057
6058 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006059 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6060 ADISPLAY_ID_DEFAULT,
6061 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006062 // The first window gets a move and the second a down
6063 firstWindow->consumeMotionMove();
6064 secondWindow->consumeMotionDown();
6065
6066 // Send pointer cancel to the second window
6067 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006068 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006069 {pointInFirst, pointInSecond});
6070 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006071 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006072 // The first window gets move and the second gets cancel.
6073 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6074 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6075
6076 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006077 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6078 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006079 // The first window gets up and the second gets nothing.
6080 firstWindow->consumeMotionUp();
6081 secondWindow->assertNoEvents();
6082}
6083
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006084TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6086
6087 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006088 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006089 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006090 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6091 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6092 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6093
Harry Cutts33476232023-01-30 19:57:29 +00006094 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006095 window->assertNoEvents();
6096 mDispatcher->waitForIdle();
6097}
6098
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006099using InputDispatcherMonitorTest = InputDispatcherTest;
6100
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006101/**
6102 * Two entities that receive touch: A window, and a global monitor.
6103 * The touch goes to the window, and then the window disappears.
6104 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6105 * for the monitor, as well.
6106 * 1. foregroundWindow
6107 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6108 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006109TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6111 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006112 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006113
Prabir Pradhanfb549072023-10-05 19:17:36 +00006114 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006115
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006116 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006119 {100, 200}))
6120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6121
6122 // Both the foreground window and the global monitor should receive the touch down
6123 window->consumeMotionDown();
6124 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6125
6126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006128 ADISPLAY_ID_DEFAULT, {110, 200}))
6129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6130
6131 window->consumeMotionMove();
6132 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6133
6134 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006135 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006136 window->consumeMotionCancel();
6137 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6138
6139 // If more events come in, there will be no more foreground window to send them to. This will
6140 // cause a cancel for the monitor, as well.
6141 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006142 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006143 ADISPLAY_ID_DEFAULT, {120, 200}))
6144 << "Injection should fail because the window was removed";
6145 window->assertNoEvents();
6146 // Global monitor now gets the cancel
6147 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6148}
6149
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006150TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006152 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6153 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006154 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006155
Prabir Pradhanfb549072023-10-05 19:17:36 +00006156 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006157
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006158 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006161 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006162 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006163}
6164
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006165TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006166 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006167
Chris Yea209fde2020-07-22 13:54:51 -07006168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006169 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6170 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006171 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006172
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006174 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006176 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006177 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006178
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006179 // Pilfer pointers from the monitor.
6180 // This should not do anything and the window should continue to receive events.
6181 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006182
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006184 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006185 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006187
6188 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6189 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006190}
6191
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006192TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006194 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6195 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006196 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006197 window->setWindowOffset(20, 40);
6198 window->setWindowTransform(0, 1, -1, 0);
6199
Prabir Pradhanfb549072023-10-05 19:17:36 +00006200 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006201
6202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006203 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006204 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6205 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006206 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6207 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006208 // Even though window has transform, gesture monitor must not.
6209 ASSERT_EQ(ui::Transform(), event->getTransform());
6210}
6211
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006212TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006214 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006215
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006216 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006217 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006218 << "Injection should fail if there is a monitor, but no touchable window";
6219 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006220}
6221
Linnan Lid8150952024-01-26 18:07:17 +00006222/**
6223 * Two displays
6224 * The first monitor has a foreground window, a monitor
6225 * The second window has only one monitor.
6226 * We first inject a Down event into the first display, this injection should succeed and both
6227 * the foreground window and monitor should receive a down event, then inject a Down event into
6228 * the second display as well, this injection should fail, at this point, the first display
6229 * window and monitor should not receive a cancel or any other event.
6230 * Continue to inject Move and UP events to the first display, the events should be received
6231 * normally by the foreground window and monitor.
6232 */
6233TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6235 sp<FakeWindowHandle> window =
6236 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6237
6238 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6239 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6240
6241 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6244 {100, 200}))
6245 << "The down event injected into the first display should succeed";
6246
6247 window->consumeMotionDown();
6248 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006249
6250 ASSERT_EQ(InputEventInjectionResult::FAILED,
6251 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6252 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006253 << "The down event injected into the second display should fail since there's no "
6254 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006255
6256 // Continue to inject event to first display.
6257 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6258 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6259 ADISPLAY_ID_DEFAULT, {110, 220}))
6260 << "The move event injected into the first display should succeed";
6261
6262 window->consumeMotionMove();
6263 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006264
6265 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6266 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6267 {110, 220}))
6268 << "The up event injected into the first display should succeed";
6269
6270 window->consumeMotionUp();
6271 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006272
6273 window->assertNoEvents();
6274 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006275 secondMonitor.assertNoEvents();
6276}
6277
6278/**
6279 * Two displays
6280 * There is a monitor and foreground window on each display.
6281 * First, we inject down events into each of the two displays, at this point, the foreground windows
6282 * and monitors on both displays should receive down events.
6283 * At this point, the foreground window of the second display goes away, the gone window should
6284 * receive the cancel event, and the other windows and monitors should not receive any events.
6285 * Inject a move event into the second display. At this point, the injection should fail because
6286 * the second display no longer has a foreground window. At this point, the monitor on the second
6287 * display should receive a cancel event, and any windows or monitors on the first display should
6288 * not receive any events, and any subsequent injection of events into the second display should
6289 * also fail.
6290 * Continue to inject events into the first display, and the events should all be injected
6291 * successfully and received normally.
6292 */
6293TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6295 sp<FakeWindowHandle> window =
6296 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6297 sp<FakeWindowHandle> secondWindow =
6298 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6299 SECOND_DISPLAY_ID);
6300
6301 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6302 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6303
6304 // There is a foreground window on both displays.
6305 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6307 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6308 {100, 200}))
6309 << "The down event injected into the first display should succeed";
6310
6311 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6312 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006313
6314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6315 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6316 {100, 200}))
6317 << "The down event injected into the second display should succeed";
6318
Linnan Lid8150952024-01-26 18:07:17 +00006319 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6320 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6321
6322 // Now second window is gone away.
6323 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6324
6325 // The gone window should receive a cancel, and the monitor on the second display should not
6326 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006327 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6328 secondMonitor.assertNoEvents();
6329
6330 ASSERT_EQ(InputEventInjectionResult::FAILED,
6331 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6332 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006333 << "The move event injected into the second display should fail because there's no "
6334 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006335 // Now the monitor on the second display should receive a cancel event.
6336 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006337
6338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6339 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6340 ADISPLAY_ID_DEFAULT, {110, 200}))
6341 << "The move event injected into the first display should succeed";
6342
6343 window->consumeMotionMove();
6344 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006345
6346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006347 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6348 {110, 220}))
6349 << "The up event injected into the second display should fail because there's no "
6350 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006351
6352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6353 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6354 {110, 220}))
6355 << "The up event injected into the first display should succeed";
6356
6357 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6358 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006359
Linnan Lid8150952024-01-26 18:07:17 +00006360 window->assertNoEvents();
6361 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006362 secondWindow->assertNoEvents();
6363 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006364}
6365
6366/**
6367 * One display with transform
6368 * There is a foreground window and a monitor on the display
6369 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6370 * event and move event, then let the foreground window go away, the foreground window receives
6371 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6372 * by the monitor should be with the same transform as the display
6373 */
6374TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6375 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6376 sp<FakeWindowHandle> window =
6377 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6378 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6379
6380 ui::Transform transform;
6381 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6382
6383 gui::DisplayInfo displayInfo;
6384 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6385 displayInfo.transform = transform;
6386
6387 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6388
6389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6390 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6391 {100, 200}))
6392 << "The down event injected should succeed";
6393
6394 window->consumeMotionDown();
6395 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6396 EXPECT_EQ(transform, downMotionEvent->getTransform());
6397 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6398
6399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6400 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6401 ADISPLAY_ID_DEFAULT, {110, 220}))
6402 << "The move event injected should succeed";
6403
6404 window->consumeMotionMove();
6405 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6406 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6407 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6408
6409 // Let foreground window gone
6410 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6411
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006412 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006413 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006414
6415 ASSERT_EQ(InputEventInjectionResult::FAILED,
6416 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6417 ADISPLAY_ID_DEFAULT, {110, 220}))
6418 << "The move event injected should failed";
6419 // Now foreground should not receive any events, but monitor should receive a cancel event
6420 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006421 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6422 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6423 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6424 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6425
6426 // Other event inject to this display should fail.
6427 ASSERT_EQ(InputEventInjectionResult::FAILED,
6428 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6429 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006430 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006431 window->assertNoEvents();
6432 monitor.assertNoEvents();
6433}
6434
chaviw81e2bb92019-12-18 15:03:51 -08006435TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006436 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006437 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6438 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006439
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006440 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006441
6442 NotifyMotionArgs motionArgs =
6443 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6444 ADISPLAY_ID_DEFAULT);
6445
Prabir Pradhan678438e2023-04-13 19:32:51 +00006446 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006447 // Window should receive motion down event.
6448 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6449
6450 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006451 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006452 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6453 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6454 motionArgs.pointerCoords[0].getX() - 10);
6455
Prabir Pradhan678438e2023-04-13 19:32:51 +00006456 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006457 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006458}
6459
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006460/**
6461 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6462 * the device default right away. In the test scenario, we check both the default value,
6463 * and the action of enabling / disabling.
6464 */
6465TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006466 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006467 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6468 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006469 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006470
6471 // Set focused application.
6472 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006473 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006474
6475 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006476 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006477 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006478 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006479
6480 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006481 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006482 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006483 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006484
6485 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006486 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006487 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006488 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006489 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006490 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006491 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006492 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006493
6494 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006495 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006496 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006497 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006498
6499 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006500 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006501 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006502 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006503 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006504 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006505 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006506 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006507
6508 window->assertNoEvents();
6509}
6510
Gang Wange9087892020-01-07 12:17:14 -05006511TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6514 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006515
6516 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006517 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006520 setFocusedWindow(window);
6521
Harry Cutts33476232023-01-30 19:57:29 +00006522 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006523
Prabir Pradhan678438e2023-04-13 19:32:51 +00006524 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6525 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006526
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006527 std::unique_ptr<KeyEvent> event = window->consumeKey();
6528 ASSERT_NE(event, nullptr);
6529 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006530 ASSERT_NE(verified, nullptr);
6531 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6532
6533 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6534 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6535 ASSERT_EQ(keyArgs.source, verified->source);
6536 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6537
6538 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6539
6540 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006541 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006542 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006543 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6544 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6545 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6546 ASSERT_EQ(0, verifiedKey.repeatCount);
6547}
6548
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006549TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006550 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006551 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6552 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006553
6554 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6555
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006556 ui::Transform transform;
6557 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6558
6559 gui::DisplayInfo displayInfo;
6560 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6561 displayInfo.transform = transform;
6562
Patrick Williamsd828f302023-04-28 17:52:08 -05006563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006564
Prabir Pradhan678438e2023-04-13 19:32:51 +00006565 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006566 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6567 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006568 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006569
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006570 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6571 ASSERT_NE(nullptr, event);
6572 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006573 ASSERT_NE(verified, nullptr);
6574 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6575
6576 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6577 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6578 EXPECT_EQ(motionArgs.source, verified->source);
6579 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6580
6581 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6582
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006583 const vec2 rawXY =
6584 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6585 motionArgs.pointerCoords[0].getXYValue());
6586 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6587 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006588 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006589 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006590 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006591 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6592 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6593}
6594
chaviw09c8d2d2020-08-24 15:48:26 -07006595/**
6596 * Ensure that separate calls to sign the same data are generating the same key.
6597 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6598 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6599 * tests.
6600 */
6601TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6602 KeyEvent event = getTestKeyEvent();
6603 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6604
6605 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6606 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6607 ASSERT_EQ(hmac1, hmac2);
6608}
6609
6610/**
6611 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6612 */
6613TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6614 KeyEvent event = getTestKeyEvent();
6615 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6616 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6617
6618 verifiedEvent.deviceId += 1;
6619 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6620
6621 verifiedEvent.source += 1;
6622 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6623
6624 verifiedEvent.eventTimeNanos += 1;
6625 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6626
6627 verifiedEvent.displayId += 1;
6628 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6629
6630 verifiedEvent.action += 1;
6631 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6632
6633 verifiedEvent.downTimeNanos += 1;
6634 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6635
6636 verifiedEvent.flags += 1;
6637 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6638
6639 verifiedEvent.keyCode += 1;
6640 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6641
6642 verifiedEvent.scanCode += 1;
6643 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6644
6645 verifiedEvent.metaState += 1;
6646 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6647
6648 verifiedEvent.repeatCount += 1;
6649 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6650}
6651
Vishnu Nair958da932020-08-21 17:12:37 -07006652TEST_F(InputDispatcherTest, SetFocusedWindow) {
6653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6654 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006655 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006656 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006657 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006658 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6659
6660 // Top window is also focusable but is not granted focus.
6661 windowTop->setFocusable(true);
6662 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006663 mDispatcher->onWindowInfosChanged(
6664 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006665 setFocusedWindow(windowSecond);
6666
6667 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006669 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006670
6671 // Focused window should receive event.
6672 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6673 windowTop->assertNoEvents();
6674}
6675
6676TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6678 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006679 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006680 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6681
6682 window->setFocusable(true);
6683 // Release channel for window is no longer valid.
6684 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006685 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006686 setFocusedWindow(window);
6687
6688 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006689 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006690
6691 // window channel is invalid, so it should not receive any input event.
6692 window->assertNoEvents();
6693}
6694
6695TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6697 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006698 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006699 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006700 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6701
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006702 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006703 setFocusedWindow(window);
6704
6705 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006706 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006707
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006708 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006709 window->assertNoEvents();
6710}
6711
6712TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6714 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006715 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006716 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006717 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006718 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6719
6720 windowTop->setFocusable(true);
6721 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006722 mDispatcher->onWindowInfosChanged(
6723 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006724 setFocusedWindow(windowTop);
6725 windowTop->consumeFocusEvent(true);
6726
Chavi Weingarten847e8512023-03-29 00:26:09 +00006727 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006728 mDispatcher->onWindowInfosChanged(
6729 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006730 windowSecond->consumeFocusEvent(true);
6731 windowTop->consumeFocusEvent(false);
6732
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006734 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006735
6736 // Focused window should receive event.
6737 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6738}
6739
Chavi Weingarten847e8512023-03-29 00:26:09 +00006740TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6742 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006743 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006744 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006745 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006746 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6747
6748 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006749 windowSecond->setFocusable(false);
6750 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006751 mDispatcher->onWindowInfosChanged(
6752 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006753 setFocusedWindow(windowTop);
6754 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006755
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006757 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006758
6759 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006760 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006761 windowSecond->assertNoEvents();
6762}
6763
6764TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6766 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006767 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006768 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006769 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6770 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006771 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6772
6773 window->setFocusable(true);
6774 previousFocusedWindow->setFocusable(true);
6775 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006776 mDispatcher->onWindowInfosChanged(
6777 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006778 setFocusedWindow(previousFocusedWindow);
6779 previousFocusedWindow->consumeFocusEvent(true);
6780
6781 // Requesting focus on invisible window takes focus from currently focused window.
6782 setFocusedWindow(window);
6783 previousFocusedWindow->consumeFocusEvent(false);
6784
6785 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006787 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6788 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006789
6790 // Window does not get focus event or key down.
6791 window->assertNoEvents();
6792
6793 // Window becomes visible.
6794 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006795 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006796
6797 // Window receives focus event.
6798 window->consumeFocusEvent(true);
6799 // Focused window receives key down.
6800 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6801}
6802
Vishnu Nair599f1412021-06-21 10:39:58 -07006803TEST_F(InputDispatcherTest, DisplayRemoved) {
6804 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6805 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006806 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006807 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6808
6809 // window is granted focus.
6810 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006812 setFocusedWindow(window);
6813 window->consumeFocusEvent(true);
6814
6815 // When a display is removed window loses focus.
6816 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6817 window->consumeFocusEvent(false);
6818}
6819
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006820/**
6821 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6822 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6823 * of the 'slipperyEnterWindow'.
6824 *
6825 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6826 * a way so that the touched location is no longer covered by the top window.
6827 *
6828 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6829 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6830 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6831 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6832 * with ACTION_DOWN).
6833 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6834 * window moved itself away from the touched location and had Flag::SLIPPERY.
6835 *
6836 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6837 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6838 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6839 *
6840 * In this test, we ensure that the event received by the bottom window has
6841 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6842 */
6843TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006844 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006845 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006846
6847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6848 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6849
6850 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006851 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006852 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006853 // Make sure this one overlaps the bottom window
6854 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6855 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6856 // one. Windows with the same owner are not considered to be occluding each other.
6857 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6858
6859 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006860 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006861 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6862
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006863 mDispatcher->onWindowInfosChanged(
6864 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006865
6866 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006867 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6868 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6869 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006870 slipperyExitWindow->consumeMotionDown();
6871 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006872 mDispatcher->onWindowInfosChanged(
6873 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006874
Prabir Pradhan678438e2023-04-13 19:32:51 +00006875 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6876 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6877 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006878
6879 slipperyExitWindow->consumeMotionCancel();
6880
6881 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6882 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6883}
6884
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006885/**
6886 * Two windows, one on the left and another on the right. The left window is slippery. The right
6887 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6888 * touch moves from the left window into the right window, the gesture should continue to go to the
6889 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6890 * reproduces a crash.
6891 */
6892TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6894
6895 sp<FakeWindowHandle> leftSlipperyWindow =
6896 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6897 leftSlipperyWindow->setSlippery(true);
6898 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6899
6900 sp<FakeWindowHandle> rightDropTouchesWindow =
6901 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6902 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6903 rightDropTouchesWindow->setDropInput(true);
6904
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006905 mDispatcher->onWindowInfosChanged(
6906 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006907
6908 // Start touch in the left window
6909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6910 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6911 .build());
6912 leftSlipperyWindow->consumeMotionDown();
6913
6914 // And move it into the right window
6915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6916 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6917 .build());
6918
6919 // Since the right window isn't eligible to receive input, touch does not slip.
6920 // The left window continues to receive the gesture.
6921 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6922 rightDropTouchesWindow->assertNoEvents();
6923}
6924
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006925/**
6926 * A single window is on screen first. Touch is injected into that window. Next, a second window
6927 * appears. Since the first window is slippery, touch will move from the first window to the second.
6928 */
6929TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6931 sp<FakeWindowHandle> originalWindow =
6932 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6933 originalWindow->setFrame(Rect(0, 0, 200, 200));
6934 originalWindow->setSlippery(true);
6935
6936 sp<FakeWindowHandle> appearingWindow =
6937 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6938 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6939
6940 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6941
6942 // Touch down on the original window
6943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6944 injectMotionEvent(*mDispatcher,
6945 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6946 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6947 .build()));
6948 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6949
6950 // Now, a new window appears. This could be, for example, a notification shade that appears
6951 // after user starts to drag down on the launcher window.
6952 mDispatcher->onWindowInfosChanged(
6953 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6955 injectMotionEvent(*mDispatcher,
6956 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6957 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6958 .build()));
6959 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6960 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6962 injectMotionEvent(*mDispatcher,
6963 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6964 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6965 .build()));
6966 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6967
6968 originalWindow->assertNoEvents();
6969 appearingWindow->assertNoEvents();
6970}
6971
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006972TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006973 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6975
6976 sp<FakeWindowHandle> leftWindow =
6977 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6978 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006979 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006980
6981 sp<FakeWindowHandle> rightSpy =
6982 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6983 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006984 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006985 rightSpy->setSpy(true);
6986 rightSpy->setTrustedOverlay(true);
6987
6988 sp<FakeWindowHandle> rightWindow =
6989 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6990 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006991 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006992
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006993 mDispatcher->onWindowInfosChanged(
6994 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006995
6996 // Touch in the left window
6997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6998 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6999 .build());
7000 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7001 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007002 ASSERT_NO_FATAL_FAILURE(
7003 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007004
7005 // Touch another finger over the right windows
7006 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7007 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7008 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7009 .build());
7010 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7011 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7012 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7013 mDispatcher->waitForIdle();
7014 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007015 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7016 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007017
7018 // Release finger over left window. The UP actions are not treated as device interaction.
7019 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7020 // is part of the UP action, we do not treat this as device interaction.
7021 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7022 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7023 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7024 .build());
7025 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7026 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7027 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7028 mDispatcher->waitForIdle();
7029 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7030
7031 // Move remaining finger
7032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7033 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7034 .build());
7035 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7036 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7037 mDispatcher->waitForIdle();
7038 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007039 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007040
7041 // Release all fingers
7042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7043 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7044 .build());
7045 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7046 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7047 mDispatcher->waitForIdle();
7048 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7049}
7050
7051TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7052 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7053
7054 sp<FakeWindowHandle> window =
7055 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7056 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007057 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007058
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007059 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007060 setFocusedWindow(window);
7061 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7062
7063 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
7064 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
7065 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007066 ASSERT_NO_FATAL_FAILURE(
7067 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007068
7069 // The UP actions are not treated as device interaction.
7070 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7071 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7072 mDispatcher->waitForIdle();
7073 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7074}
7075
Prabir Pradhan5893d362023-11-17 04:30:40 +00007076TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7078
7079 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7080 ADISPLAY_ID_DEFAULT);
7081 left->setFrame(Rect(0, 0, 100, 100));
7082 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7083 "Right Window", ADISPLAY_ID_DEFAULT);
7084 right->setFrame(Rect(100, 0, 200, 100));
7085 sp<FakeWindowHandle> spy =
7086 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7087 spy->setFrame(Rect(0, 0, 200, 100));
7088 spy->setTrustedOverlay(true);
7089 spy->setSpy(true);
7090
7091 mDispatcher->onWindowInfosChanged(
7092 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7093
7094 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7095 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7096 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7097 mDispatcher->notifyMotion(notifyArgs);
7098
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007099 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007100 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7101 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007102 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007103 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7104 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007105 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007106 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7107
7108 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7109 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7110 {PointF{150, 50}});
7111 mDispatcher->notifyMotion(notifyArgs);
7112
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007113 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007114 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7115 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007116 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007117 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7118 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007119 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007120 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7121
7122 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7123}
7124
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007125class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7126protected:
7127 std::shared_ptr<FakeApplicationHandle> mApp;
7128 sp<FakeWindowHandle> mWindow;
7129
7130 virtual void SetUp() override {
7131 InputDispatcherTest::SetUp();
7132
7133 mApp = std::make_shared<FakeApplicationHandle>();
7134
7135 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7136 mWindow->setFrame(Rect(0, 0, 100, 100));
7137
7138 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7139 setFocusedWindow(mWindow);
7140 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7141 }
7142
7143 void setFallback(int32_t keycode) {
7144 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7145 return KeyEventBuilder(event).keyCode(keycode).build();
7146 });
7147 }
7148
7149 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007150 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7151 ASSERT_NE(nullptr, event);
7152 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007153 }
7154};
7155
7156TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7157 mDispatcher->notifyKey(
7158 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7159 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7160 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7161}
7162
7163TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7164 mDispatcher->notifyKey(
7165 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7166 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7167 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7168}
7169
7170TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7171 mDispatcher->notifyKey(
7172 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7173
7174 // Do not handle this key event.
7175 consumeKey(/*handled=*/false,
7176 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7177 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7178
7179 // Since the policy did not request any fallback to be generated, ensure there are no events.
7180 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7181}
7182
7183TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7184 setFallback(AKEYCODE_B);
7185 mDispatcher->notifyKey(
7186 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7187
7188 // Do not handle this key event.
7189 consumeKey(/*handled=*/false,
7190 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7191
7192 // Since the key was not handled, ensure the fallback event was dispatched instead.
7193 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7194 consumeKey(/*handled=*/true,
7195 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7196 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7197
7198 // Release the original key, and ensure the fallback key is also released.
7199 mDispatcher->notifyKey(
7200 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7201 consumeKey(/*handled=*/false,
7202 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7203 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7204 consumeKey(/*handled=*/true,
7205 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7206 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7207
7208 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7209 mWindow->assertNoEvents();
7210}
7211
7212TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7213 setFallback(AKEYCODE_B);
7214 mDispatcher->notifyKey(
7215 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7216
7217 // Do not handle this key event, but handle the fallback.
7218 consumeKey(/*handled=*/false,
7219 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7220 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7221 consumeKey(/*handled=*/true,
7222 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7223 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7224
7225 // Release the original key, and ensure the fallback key is also released.
7226 mDispatcher->notifyKey(
7227 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7228 // But this time, the app handles the original key.
7229 consumeKey(/*handled=*/true,
7230 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7231 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7232 // Ensure the fallback key is canceled.
7233 consumeKey(/*handled=*/true,
7234 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7235 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7236
7237 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7238 mWindow->assertNoEvents();
7239}
7240
7241TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7242 setFallback(AKEYCODE_B);
7243 mDispatcher->notifyKey(
7244 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7245
7246 // Do not handle this key event.
7247 consumeKey(/*handled=*/false,
7248 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7249 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7250 // App does not handle the fallback either, so ensure another fallback is not generated.
7251 setFallback(AKEYCODE_C);
7252 consumeKey(/*handled=*/false,
7253 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7254 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7255
7256 // Release the original key, and ensure the fallback key is also released.
7257 setFallback(AKEYCODE_B);
7258 mDispatcher->notifyKey(
7259 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7260 consumeKey(/*handled=*/false,
7261 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7263 consumeKey(/*handled=*/false,
7264 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7265 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7266
7267 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7268 mWindow->assertNoEvents();
7269}
7270
7271TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7272 setFallback(AKEYCODE_B);
7273 mDispatcher->notifyKey(
7274 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7275
7276 // Do not handle this key event, so fallback is generated.
7277 consumeKey(/*handled=*/false,
7278 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7279 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7280 consumeKey(/*handled=*/true,
7281 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7282 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7283
7284 // Release the original key, but assume the policy is misbehaving and it
7285 // generates an inconsistent fallback to the one from the DOWN event.
7286 setFallback(AKEYCODE_C);
7287 mDispatcher->notifyKey(
7288 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7289 consumeKey(/*handled=*/false,
7290 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7291 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7292 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7293 consumeKey(/*handled=*/true,
7294 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7295 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7296
7297 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7298 mWindow->assertNoEvents();
7299}
7300
7301TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7302 setFallback(AKEYCODE_B);
7303 mDispatcher->notifyKey(
7304 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7305
7306 // Do not handle this key event, so fallback is generated.
7307 consumeKey(/*handled=*/false,
7308 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7309 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7310 consumeKey(/*handled=*/true,
7311 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7312 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7313
7314 // The original key is canceled.
7315 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7316 .keyCode(AKEYCODE_A)
7317 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7318 .build());
7319 consumeKey(/*handled=*/false,
7320 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7321 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7322 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7323 // Ensure the fallback key is also canceled due to the original key being canceled.
7324 consumeKey(/*handled=*/true,
7325 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7326 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7327
7328 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7329 mWindow->assertNoEvents();
7330}
7331
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007332TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007333 setFallback(AKEYCODE_B);
7334 mDispatcher->notifyKey(
7335 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7336
7337 // Do not handle this key event.
7338 consumeKey(/*handled=*/false,
7339 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7340 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7341 consumeKey(/*handled=*/true,
7342 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7343 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7344
7345 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7346 // When the unhandled key is reported to the policy next, remove the input channel.
7347 mDispatcher->removeInputChannel(mWindow->getToken());
7348 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7349 });
7350 // Release the original key, and let the app now handle the previously unhandled key.
7351 // This should result in the previously generated fallback key to be cancelled.
7352 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7353 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7354 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7355 // the policy call, we will now remove the input channel. Once the policy call returns, the
7356 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7357 // not cause any crashes.
7358 mDispatcher->notifyKey(
7359 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7360 consumeKey(/*handled=*/true,
7361 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7362 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7363}
7364
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007365TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7366 setFallback(AKEYCODE_B);
7367 mDispatcher->notifyKey(
7368 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7369
7370 // Do not handle this key event.
7371 consumeKey(/*handled=*/false,
7372 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7373 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7374 consumeKey(/*handled=*/true,
7375 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7376 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7377
7378 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7379 // When the unhandled key is reported to the policy next, remove the window.
7380 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7381 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7382 });
7383 // Release the original key, which the app will not handle. When this unhandled key is reported
7384 // to the policy, the window will be removed.
7385 mDispatcher->notifyKey(
7386 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7387 consumeKey(/*handled=*/false,
7388 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7389 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7390
7391 // Since the window was removed, it loses focus, and the channel state will be reset.
7392 consumeKey(/*handled=*/true,
7393 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7394 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7395 mWindow->consumeFocusEvent(false);
7396 mWindow->assertNoEvents();
7397}
7398
7399TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7400 setFallback(AKEYCODE_B);
7401 mDispatcher->notifyKey(
7402 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7403
7404 // Do not handle this key event.
7405 consumeKey(/*handled=*/false,
7406 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7407 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7408 const auto [seq, event] = mWindow->receiveEvent();
7409 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7410 ASSERT_EQ(event->getType(), InputEventType::KEY);
7411 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7412 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7413 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7414
7415 // Remove the window now, which should generate a cancellations and make the window lose focus.
7416 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7417 consumeKey(/*handled=*/true,
7418 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7419 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7420 consumeKey(/*handled=*/true,
7421 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7422 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7423 mWindow->consumeFocusEvent(false);
7424
7425 // Finish the event by reporting it as handled.
7426 mWindow->finishEvent(*seq);
7427 mWindow->assertNoEvents();
7428}
7429
Garfield Tan1c7bc862020-01-28 13:24:04 -08007430class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7431protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007432 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7433 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007434
Chris Yea209fde2020-07-22 13:54:51 -07007435 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007436 sp<FakeWindowHandle> mWindow;
7437
7438 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007439 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007440
Prabir Pradhandae52792023-12-15 07:36:40 +00007441 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007442 setUpWindow();
7443 }
7444
7445 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007446 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007447 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007448
Vishnu Nair47074b82020-08-14 11:54:47 -07007449 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007450 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007451 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007452 mWindow->consumeFocusEvent(true);
7453 }
7454
Chris Ye2ad95392020-09-01 13:44:44 -07007455 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007456 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007457 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007458 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007459 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007460
7461 // Window should receive key down event.
7462 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7463 }
7464
7465 void expectKeyRepeatOnce(int32_t repeatCount) {
7466 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007467 mWindow->consumeKeyEvent(
7468 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007469 }
7470
Chris Ye2ad95392020-09-01 13:44:44 -07007471 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007472 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007473 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007474 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007475 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007476
7477 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007478 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007479 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007480 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007481
7482 void injectKeyRepeat(int32_t repeatCount) {
7483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7484 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7485 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7486 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007487};
7488
7489TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007490 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007491 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7492 expectKeyRepeatOnce(repeatCount);
7493 }
7494}
7495
7496TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007497 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007498 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7499 expectKeyRepeatOnce(repeatCount);
7500 }
Harry Cutts33476232023-01-30 19:57:29 +00007501 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007502 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007503 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7504 expectKeyRepeatOnce(repeatCount);
7505 }
7506}
7507
7508TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007509 sendAndConsumeKeyDown(/*deviceId=*/1);
7510 expectKeyRepeatOnce(/*repeatCount=*/1);
7511 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007512 mWindow->assertNoEvents();
7513}
7514
7515TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007516 sendAndConsumeKeyDown(/*deviceId=*/1);
7517 expectKeyRepeatOnce(/*repeatCount=*/1);
7518 sendAndConsumeKeyDown(/*deviceId=*/2);
7519 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007520 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007521 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007522 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007523 expectKeyRepeatOnce(/*repeatCount=*/2);
7524 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007525 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007526 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007527 mWindow->assertNoEvents();
7528}
7529
7530TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007531 sendAndConsumeKeyDown(/*deviceId=*/1);
7532 expectKeyRepeatOnce(/*repeatCount=*/1);
7533 sendAndConsumeKeyDown(/*deviceId=*/2);
7534 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007535 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007536 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007537 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007538 mWindow->assertNoEvents();
7539}
7540
liushenxiang42232912021-05-21 20:24:09 +08007541TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7542 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007543 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007544 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007545 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7546 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7547 mWindow->assertNoEvents();
7548}
7549
Garfield Tan1c7bc862020-01-28 13:24:04 -08007550TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007551 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007552 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007553 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007554 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7555 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007556 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007557 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007558 }
7559}
7560
7561TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007562 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007563 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007564
7565 std::unordered_set<int32_t> idSet;
7566 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007567 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7568 ASSERT_NE(nullptr, repeatEvent);
7569 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007570 EXPECT_EQ(idSet.end(), idSet.find(id));
7571 idSet.insert(id);
7572 }
7573}
7574
Hu Guofe3c8f12023-09-22 17:20:15 +08007575TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7576 injectKeyRepeat(0);
7577 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7578 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7579 expectKeyRepeatOnce(repeatCount);
7580 }
7581 injectKeyRepeat(1);
7582 // Expect repeatCount to be 3 instead of 1
7583 expectKeyRepeatOnce(3);
7584}
7585
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007586/* Test InputDispatcher for MultiDisplay */
7587class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7588public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007589 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007590 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007591
Chris Yea209fde2020-07-22 13:54:51 -07007592 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007593 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007594 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007595
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007596 // Set focus window for primary display, but focused display would be second one.
7597 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007598 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007599 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7600
Vishnu Nair958da932020-08-21 17:12:37 -07007601 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007602 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007603
Chris Yea209fde2020-07-22 13:54:51 -07007604 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007605 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007606 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007607 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007608 // Set focus display to second one.
7609 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7610 // Set focus window for second display.
7611 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007612 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007613 mDispatcher->onWindowInfosChanged(
7614 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007615 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007616 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007617 }
7618
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007619 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007620 InputDispatcherTest::TearDown();
7621
Chris Yea209fde2020-07-22 13:54:51 -07007622 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007623 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007624 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007625 windowInSecondary.clear();
7626 }
7627
7628protected:
Chris Yea209fde2020-07-22 13:54:51 -07007629 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007630 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007631 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007632 sp<FakeWindowHandle> windowInSecondary;
7633};
7634
7635TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7636 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007638 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007640 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007641 windowInSecondary->assertNoEvents();
7642
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007643 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007645 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007647 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007648 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007649}
7650
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007651TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007652 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007654 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007655 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007656 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007657 windowInSecondary->assertNoEvents();
7658
7659 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007661 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007662 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007663 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007664
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007665 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007666 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007667
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007668 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007669 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007670
7671 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007672 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007673 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007674 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007675 windowInSecondary->assertNoEvents();
7676}
7677
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007678// Test per-display input monitors for motion event.
7679TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007680 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007681 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007682 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007683 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007684
7685 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007689 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007690 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007691 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007692 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007693
7694 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007696 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007697 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007698 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007699 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007700 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007701 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007702
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007703 // Lift up the touch from the second display
7704 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007705 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007706 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7707 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7708 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7709
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007710 // Test inject a non-pointer motion event.
7711 // If specific a display, it will dispatch to the focused window of particular display,
7712 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007714 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007716 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007717 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007718 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007719 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007720}
7721
7722// Test per-display input monitors for key event.
7723TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007724 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007725 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007726 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007727 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007728 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007729
7730 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007732 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007733 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007734 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007735 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007736 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007737}
7738
Vishnu Nair958da932020-08-21 17:12:37 -07007739TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7740 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007741 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007742 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007743 mDispatcher->onWindowInfosChanged(
7744 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7745 *windowInSecondary->getInfo()},
7746 {},
7747 0,
7748 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007749 setFocusedWindow(secondWindowInPrimary);
7750 windowInPrimary->consumeFocusEvent(false);
7751 secondWindowInPrimary->consumeFocusEvent(true);
7752
7753 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7755 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007757 windowInPrimary->assertNoEvents();
7758 windowInSecondary->assertNoEvents();
7759 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7760}
7761
Arthur Hungdfd528e2021-12-08 13:23:04 +00007762TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7763 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007764 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007765 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007766 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007767
7768 // Test touch down on primary display.
7769 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007770 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7772 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7773 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7774
7775 // Test touch down on second display.
7776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7779 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7780 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7781
7782 // Trigger cancel touch.
7783 mDispatcher->cancelCurrentTouch();
7784 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7785 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7786 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7787 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7788
7789 // Test inject a move motion event, no window/monitor should receive the event.
7790 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007791 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007792 ADISPLAY_ID_DEFAULT, {110, 200}))
7793 << "Inject motion event should return InputEventInjectionResult::FAILED";
7794 windowInPrimary->assertNoEvents();
7795 monitorInPrimary.assertNoEvents();
7796
7797 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007798 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007799 SECOND_DISPLAY_ID, {110, 200}))
7800 << "Inject motion event should return InputEventInjectionResult::FAILED";
7801 windowInSecondary->assertNoEvents();
7802 monitorInSecondary.assertNoEvents();
7803}
7804
Hu Guocb134f12023-12-23 13:42:44 +00007805/**
7806 * Send a key to the primary display and to the secondary display.
7807 * Then cause the key on the primary display to be canceled by sending in a stale key.
7808 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7809 * does not get canceled.
7810 */
7811TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7812 // Send a key down on primary display
7813 mDispatcher->notifyKey(
7814 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7815 .displayId(ADISPLAY_ID_DEFAULT)
7816 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7817 .build());
7818 windowInPrimary->consumeKeyEvent(
7819 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7820 windowInSecondary->assertNoEvents();
7821
7822 // Send a key down on second display
7823 mDispatcher->notifyKey(
7824 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7825 .displayId(SECOND_DISPLAY_ID)
7826 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7827 .build());
7828 windowInSecondary->consumeKeyEvent(
7829 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7830 windowInPrimary->assertNoEvents();
7831
7832 // Send a valid key up event on primary display that will be dropped because it is stale
7833 NotifyKeyArgs staleKeyUp =
7834 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7835 .displayId(ADISPLAY_ID_DEFAULT)
7836 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7837 .build();
7838 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7839 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7840 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7841 mDispatcher->notifyKey(staleKeyUp);
7842
7843 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7844 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7845 // receive any events.
7846 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7847 WithDisplayId(ADISPLAY_ID_DEFAULT),
7848 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7849 windowInSecondary->assertNoEvents();
7850}
7851
7852/**
7853 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7854 */
7855TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7856 // Send touch down on primary display.
7857 mDispatcher->notifyMotion(
7858 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7859 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7860 .displayId(ADISPLAY_ID_DEFAULT)
7861 .build());
7862 windowInPrimary->consumeMotionEvent(
7863 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7864 windowInSecondary->assertNoEvents();
7865
7866 // Send touch down on second display.
7867 mDispatcher->notifyMotion(
7868 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7869 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7870 .displayId(SECOND_DISPLAY_ID)
7871 .build());
7872 windowInPrimary->assertNoEvents();
7873 windowInSecondary->consumeMotionEvent(
7874 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7875
7876 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7877 NotifyMotionArgs staleMotionUp =
7878 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7879 .displayId(ADISPLAY_ID_DEFAULT)
7880 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7881 .build();
7882 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7883 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7884 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7885 mDispatcher->notifyMotion(staleMotionUp);
7886
7887 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7888 // events, where we would cancel the current keys instead.
7889 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7890 windowInSecondary->assertNoEvents();
7891}
7892
Jackal Guof9696682018-10-05 12:23:23 +08007893class InputFilterTest : public InputDispatcherTest {
7894protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007895 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7896 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007897 NotifyMotionArgs motionArgs;
7898
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007899 motionArgs =
7900 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007901 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007902 motionArgs =
7903 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007904 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007905 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007906 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007907 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007908 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007909 } else {
7910 mFakePolicy->assertFilterInputEventWasNotCalled();
7911 }
7912 }
7913
7914 void testNotifyKey(bool expectToBeFiltered) {
7915 NotifyKeyArgs keyArgs;
7916
7917 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007918 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007919 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007920 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007921 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007922
7923 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007924 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007925 } else {
7926 mFakePolicy->assertFilterInputEventWasNotCalled();
7927 }
7928 }
7929};
7930
7931// Test InputFilter for MotionEvent
7932TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7933 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007934 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7935 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007936
7937 // Enable InputFilter
7938 mDispatcher->setInputFilterEnabled(true);
7939 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007940 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7941 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007942
7943 // Disable InputFilter
7944 mDispatcher->setInputFilterEnabled(false);
7945 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007946 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7947 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007948}
7949
7950// Test InputFilter for KeyEvent
7951TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7952 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007953 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007954
7955 // Enable InputFilter
7956 mDispatcher->setInputFilterEnabled(true);
7957 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007958 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007959
7960 // Disable InputFilter
7961 mDispatcher->setInputFilterEnabled(false);
7962 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007963 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007964}
7965
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007966// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7967// logical display coordinate space.
7968TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7969 ui::Transform firstDisplayTransform;
7970 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7971 ui::Transform secondDisplayTransform;
7972 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7973
7974 std::vector<gui::DisplayInfo> displayInfos(2);
7975 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7976 displayInfos[0].transform = firstDisplayTransform;
7977 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7978 displayInfos[1].transform = secondDisplayTransform;
7979
Patrick Williamsd828f302023-04-28 17:52:08 -05007980 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007981
7982 // Enable InputFilter
7983 mDispatcher->setInputFilterEnabled(true);
7984
7985 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007986 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7987 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007988}
7989
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007990class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7991protected:
7992 virtual void SetUp() override {
7993 InputDispatcherTest::SetUp();
7994
7995 /**
7996 * We don't need to enable input filter to test the injected event policy, but we enabled it
7997 * here to make the tests more realistic, since this policy only matters when inputfilter is
7998 * on.
7999 */
8000 mDispatcher->setInputFilterEnabled(true);
8001
8002 std::shared_ptr<InputApplicationHandle> application =
8003 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008004 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
8005 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008006
8007 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8008 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008009 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008010 setFocusedWindow(mWindow);
8011 mWindow->consumeFocusEvent(true);
8012 }
8013
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008014 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8015 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008016 KeyEvent event;
8017
8018 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8019 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
8020 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00008021 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008022 const int32_t additionalPolicyFlags =
8023 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
8024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008025 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008026 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008027 policyFlags | additionalPolicyFlags));
8028
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008029 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008030 }
8031
8032 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8033 int32_t flags) {
8034 MotionEvent event;
8035 PointerProperties pointerProperties[1];
8036 PointerCoords pointerCoords[1];
8037 pointerProperties[0].clear();
8038 pointerProperties[0].id = 0;
8039 pointerCoords[0].clear();
8040 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
8041 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
8042
8043 ui::Transform identityTransform;
8044 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8045 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
8046 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
8047 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
8048 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07008049 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07008050 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008051 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008052
8053 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
8054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00008055 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00008056 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008057 policyFlags | additionalPolicyFlags));
8058
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008059 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008060 }
8061
8062private:
8063 sp<FakeWindowHandle> mWindow;
8064};
8065
8066TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008067 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
8068 // filter. Without it, the event will no different from a regularly injected event, and the
8069 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00008070 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
8071 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008072}
8073
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008074TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008075 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008076 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008077 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
8078}
8079
8080TEST_F(InputFilterInjectionPolicyTest,
8081 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
8082 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008083 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008084 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008085}
8086
8087TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008088 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8089 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008090}
8091
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008092class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8093protected:
8094 virtual void SetUp() override {
8095 InputDispatcherTest::SetUp();
8096
8097 std::shared_ptr<FakeApplicationHandle> application =
8098 std::make_shared<FakeApplicationHandle>();
8099 application->setDispatchingTimeout(100ms);
8100 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8101 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008102 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008103 mWindow->setDispatchingTimeout(100ms);
8104 mWindow->setFocusable(true);
8105
8106 // Set focused application.
8107 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8108
8109 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8110 setFocusedWindow(mWindow);
8111 mWindow->consumeFocusEvent(true);
8112 }
8113
8114 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8115 nsecs_t eventTime) {
8116 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8117 .displayId(displayId)
8118 .eventTime(eventTime)
8119 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8120 .build());
8121 mWindow->consumeMotionEvent(WithMotionAction(action));
8122 }
8123
8124private:
8125 sp<FakeWindowHandle> mWindow;
8126};
8127
8128TEST_F_WITH_FLAGS(
8129 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8130 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8131 rate_limit_user_activity_poke_in_dispatcher))) {
8132 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8133
8134 // First event of type TOUCH. Should poke.
8135 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8136 milliseconds_to_nanoseconds(50));
8137 mFakePolicy->assertUserActivityPoked(
8138 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8139
8140 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8141 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8142 milliseconds_to_nanoseconds(130));
8143 mFakePolicy->assertUserActivityPoked(
8144 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8145
8146 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8147 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8148 milliseconds_to_nanoseconds(135));
8149 mFakePolicy->assertUserActivityPoked(
8150 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8151
8152 // Within 50ns of previous TOUCH event. Should NOT poke.
8153 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8154 milliseconds_to_nanoseconds(140));
8155 mFakePolicy->assertUserActivityNotPoked();
8156
8157 // Within 50ns of previous OTHER event. Should NOT poke.
8158 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8159 milliseconds_to_nanoseconds(150));
8160 mFakePolicy->assertUserActivityNotPoked();
8161
8162 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8163 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8164 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8165 milliseconds_to_nanoseconds(160));
8166 mFakePolicy->assertUserActivityNotPoked();
8167
8168 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8169 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8170 milliseconds_to_nanoseconds(200));
8171 mFakePolicy->assertUserActivityPoked(
8172 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8173
8174 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8175 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8176 milliseconds_to_nanoseconds(300));
8177 mFakePolicy->assertUserActivityPoked(
8178 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8179
8180 // Assert that there's no more user activity poke event.
8181 mFakePolicy->assertUserActivityNotPoked();
8182}
8183
8184TEST_F_WITH_FLAGS(
8185 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8186 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8187 rate_limit_user_activity_poke_in_dispatcher))) {
8188 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8189 milliseconds_to_nanoseconds(200));
8190 mFakePolicy->assertUserActivityPoked(
8191 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8192
8193 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8194 milliseconds_to_nanoseconds(280));
8195 mFakePolicy->assertUserActivityNotPoked();
8196
8197 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8198 milliseconds_to_nanoseconds(340));
8199 mFakePolicy->assertUserActivityPoked(
8200 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8201}
8202
8203TEST_F_WITH_FLAGS(
8204 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8205 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8206 rate_limit_user_activity_poke_in_dispatcher))) {
8207 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8208
8209 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8210 mFakePolicy->assertUserActivityPoked();
8211
8212 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8213 mFakePolicy->assertUserActivityPoked();
8214}
8215
chaviwfd6d3512019-03-25 13:23:49 -07008216class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008217 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008218 InputDispatcherTest::SetUp();
8219
Chris Yea209fde2020-07-22 13:54:51 -07008220 std::shared_ptr<FakeApplicationHandle> application =
8221 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008222 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008223 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008224 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008225
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008226 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008227 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008228 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008229
8230 // Set focused application.
8231 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008232 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008233
8234 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008235 mDispatcher->onWindowInfosChanged(
8236 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008237 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008238 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008239 }
8240
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008241 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008242 InputDispatcherTest::TearDown();
8243
8244 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008245 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008246 }
8247
8248protected:
8249 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008250 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008251 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008252};
8253
8254// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8255// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8256// the onPointerDownOutsideFocus callback.
8257TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008259 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008260 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008262 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008263
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008264 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008265 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8266}
8267
8268// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8269// DOWN on the window that doesn't have focus. Ensure no window received the
8270// onPointerDownOutsideFocus callback.
8271TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008273 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8274 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008276 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008277
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008278 ASSERT_TRUE(mDispatcher->waitForIdle());
8279 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008280}
8281
8282// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8283// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8284TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008286 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008288 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008289
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008290 ASSERT_TRUE(mDispatcher->waitForIdle());
8291 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008292}
8293
8294// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8295// DOWN on the window that already has focus. Ensure no window received the
8296// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008297TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008299 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008300 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008301 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008302 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008303
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008304 ASSERT_TRUE(mDispatcher->waitForIdle());
8305 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008306}
8307
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008308// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8309// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8310TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8311 const MotionEvent event =
8312 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8313 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008314 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008315 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8316 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008318 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8319 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8320
8321 ASSERT_TRUE(mDispatcher->waitForIdle());
8322 mFakePolicy->assertOnPointerDownWasNotCalled();
8323 // Ensure that the unfocused window did not receive any FOCUS events.
8324 mUnfocusedWindow->assertNoEvents();
8325}
8326
chaviwaf87b3e2019-10-01 16:59:28 -07008327// These tests ensures we can send touch events to a single client when there are multiple input
8328// windows that point to the same client token.
8329class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8330 virtual void SetUp() override {
8331 InputDispatcherTest::SetUp();
8332
Chris Yea209fde2020-07-22 13:54:51 -07008333 std::shared_ptr<FakeApplicationHandle> application =
8334 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008335 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8336 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008337 mWindow1->setFrame(Rect(0, 0, 100, 100));
8338
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008339 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008340 mWindow2->setFrame(Rect(100, 100, 200, 200));
8341
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008342 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008343 }
8344
8345protected:
8346 sp<FakeWindowHandle> mWindow1;
8347 sp<FakeWindowHandle> mWindow2;
8348
8349 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008350 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008351 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8352 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008353 }
8354
8355 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8356 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008357 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008358 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008359 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008360 ASSERT_NE(nullptr, motionEvent);
8361 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008362
8363 for (size_t i = 0; i < points.size(); i++) {
8364 float expectedX = points[i].x;
8365 float expectedY = points[i].y;
8366
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008367 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008368 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008369 << ", got " << motionEvent->getX(i);
8370 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008371 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008372 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008373 }
8374 }
chaviw9eaa22c2020-07-01 16:21:27 -07008375
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008376 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8377 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008378 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008379 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8380 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008381
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008382 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008383 }
chaviwaf87b3e2019-10-01 16:59:28 -07008384};
8385
8386TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8387 // Touch Window 1
8388 PointF touchedPoint = {10, 10};
8389 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008390 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008391
8392 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008393 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008394
8395 // Touch Window 2
8396 touchedPoint = {150, 150};
8397 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008398 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008399}
8400
chaviw9eaa22c2020-07-01 16:21:27 -07008401TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8402 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008403 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008404 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008405
8406 // Touch Window 1
8407 PointF touchedPoint = {10, 10};
8408 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008409 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008410 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008411 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008412
8413 // Touch Window 2
8414 touchedPoint = {150, 150};
8415 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008416 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8417 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008418
chaviw9eaa22c2020-07-01 16:21:27 -07008419 // Update the transform so rotation is set
8420 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008421 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008422 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008423 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008424}
8425
chaviw9eaa22c2020-07-01 16:21:27 -07008426TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008427 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008428 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008429
8430 // Touch Window 1
8431 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8432 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008433 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008434
8435 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008436 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8437 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8438 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008439 touchedPoints.push_back(PointF{150, 150});
8440 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008441 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008442
chaviw9eaa22c2020-07-01 16:21:27 -07008443 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008444 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008445 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008446
chaviw9eaa22c2020-07-01 16:21:27 -07008447 // Update the transform so rotation is set for Window 2
8448 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008449 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008450 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008451 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008452}
8453
chaviw9eaa22c2020-07-01 16:21:27 -07008454TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008455 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008456 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008457
8458 // Touch Window 1
8459 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8460 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008461 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008462
8463 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008464 touchedPoints.push_back(PointF{150, 150});
8465 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008466
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008467 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008468
8469 // Move both windows
8470 touchedPoints = {{20, 20}, {175, 175}};
8471 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8472 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8473
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008474 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008475
chaviw9eaa22c2020-07-01 16:21:27 -07008476 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008477 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008478 expectedPoints.pop_back();
8479
8480 // Touch Window 2
8481 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008482 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008483 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008484 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008485
8486 // Move both windows
8487 touchedPoints = {{20, 20}, {175, 175}};
8488 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8489 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8490
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008491 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008492}
8493
8494TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8495 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008496 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008497
8498 // Touch Window 1
8499 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8500 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008501 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008502
8503 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008504 touchedPoints.push_back(PointF{150, 150});
8505 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008506
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008507 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008508
8509 // Move both windows
8510 touchedPoints = {{20, 20}, {175, 175}};
8511 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8512 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8513
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008514 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008515}
8516
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008517/**
8518 * When one of the windows is slippery, the touch should not slip into the other window with the
8519 * same input channel.
8520 */
8521TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8522 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008523 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008524
8525 // Touch down in window 1
8526 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8527 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8528 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8529
8530 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8531 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8532 // getting generated.
8533 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8534 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8535
8536 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8537}
8538
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008539/**
8540 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8541 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8542 * that the pointer is hovering over may have a different transform.
8543 */
8544TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008545 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008546
8547 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8549 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8550 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008551 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8552 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008553 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8555 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8556 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008557 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008558 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008559 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8560}
8561
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008562class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8563 virtual void SetUp() override {
8564 InputDispatcherTest::SetUp();
8565
Chris Yea209fde2020-07-22 13:54:51 -07008566 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008567 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008568 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8569 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008570 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008571 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008572 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008573
8574 // Set focused application.
8575 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8576
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008577 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008578 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008579 mWindow->consumeFocusEvent(true);
8580 }
8581
8582 virtual void TearDown() override {
8583 InputDispatcherTest::TearDown();
8584 mWindow.clear();
8585 }
8586
8587protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008588 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008589 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008590 sp<FakeWindowHandle> mWindow;
8591 static constexpr PointF WINDOW_LOCATION = {20, 20};
8592
8593 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008594 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8595 .x(WINDOW_LOCATION.x)
8596 .y(WINDOW_LOCATION.y);
8597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8598 .pointer(touchingPointer)
8599 .build());
8600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8601 .pointer(touchingPointer)
8602 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008603 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008604
8605 sp<FakeWindowHandle> addSpyWindow() {
8606 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008607 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008608 spy->setTrustedOverlay(true);
8609 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008610 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008611 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008612 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008613 return spy;
8614 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008615};
8616
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008617// Send a tap and respond, which should not cause an ANR.
8618TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8619 tapOnWindow();
8620 mWindow->consumeMotionDown();
8621 mWindow->consumeMotionUp();
8622 ASSERT_TRUE(mDispatcher->waitForIdle());
8623 mFakePolicy->assertNotifyAnrWasNotCalled();
8624}
8625
8626// Send a regular key and respond, which should not cause an ANR.
8627TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008628 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008629 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8630 ASSERT_TRUE(mDispatcher->waitForIdle());
8631 mFakePolicy->assertNotifyAnrWasNotCalled();
8632}
8633
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008634TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8635 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008636 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008637 mWindow->consumeFocusEvent(false);
8638
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008639 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008640 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8641 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008642 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008644 // Key will not go to window because we have no focused window.
8645 // The 'no focused window' ANR timer should start instead.
8646
8647 // Now, the focused application goes away.
8648 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8649 // The key should get dropped and there should be no ANR.
8650
8651 ASSERT_TRUE(mDispatcher->waitForIdle());
8652 mFakePolicy->assertNotifyAnrWasNotCalled();
8653}
8654
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008655// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008656// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8657// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008658TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008660 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008661 WINDOW_LOCATION));
8662
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008663 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008664 ASSERT_TRUE(sequenceNum);
8665 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008666 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008667
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008668 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008669 mWindow->consumeMotionEvent(
8670 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008671 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008672 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008673}
8674
8675// Send a key to the app and have the app not respond right away.
8676TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8677 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008679 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008680 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008681 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008682 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008683 ASSERT_TRUE(mDispatcher->waitForIdle());
8684}
8685
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008686// We have a focused application, but no focused window
8687TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008688 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008689 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008690 mWindow->consumeFocusEvent(false);
8691
8692 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008694 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008695 WINDOW_LOCATION));
8696 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8697 mDispatcher->waitForIdle();
8698 mFakePolicy->assertNotifyAnrWasNotCalled();
8699
8700 // Once a focused event arrives, we get an ANR for this application
8701 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8702 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008703 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008704 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008705 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008706 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008707 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008708 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008709 ASSERT_TRUE(mDispatcher->waitForIdle());
8710}
8711
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008712/**
8713 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8714 * there will not be an ANR.
8715 */
8716TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8717 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008718 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008719 mWindow->consumeFocusEvent(false);
8720
8721 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008722 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8723 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008724 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8725 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8726
8727 // Define a valid key down event that is stale (too old).
8728 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008729 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008730 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008731
Hu Guofe3c8f12023-09-22 17:20:15 +08008732 const int32_t policyFlags =
8733 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008734
8735 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008736 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008737 InputEventInjectionSync::WAIT_FOR_RESULT,
8738 INJECT_EVENT_TIMEOUT, policyFlags);
8739 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8740 << "Injection should fail because the event is stale";
8741
8742 ASSERT_TRUE(mDispatcher->waitForIdle());
8743 mFakePolicy->assertNotifyAnrWasNotCalled();
8744 mWindow->assertNoEvents();
8745}
8746
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008747// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008748// Make sure that we don't notify policy twice about the same ANR.
8749TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008750 const std::chrono::duration appTimeout = 400ms;
8751 mApplication->setDispatchingTimeout(appTimeout);
8752 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8753
Vishnu Nair47074b82020-08-14 11:54:47 -07008754 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008755 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008756 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008757
8758 // Once a focused event arrives, we get an ANR for this application
8759 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8760 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008761 const std::chrono::duration eventInjectionTimeout = 100ms;
8762 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008763 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008764 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008765 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8766 /*allowKeyRepeat=*/false);
8767 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8768 << "result=" << ftl::enum_string(result);
8769 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8770 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8771 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8772 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008773
Vishnu Naire4df8752022-09-08 09:17:55 -07008774 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008775 // ANR should not be raised again. It is up to policy to do that if it desires.
8776 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008777
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008778 // If we now get a focused window, the ANR should stop, but the policy handles that via
8779 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008780 ASSERT_TRUE(mDispatcher->waitForIdle());
8781}
8782
8783// We have a focused application, but no focused window
8784TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008785 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008786 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008787 mWindow->consumeFocusEvent(false);
8788
8789 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008790 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008791
Vishnu Naire4df8752022-09-08 09:17:55 -07008792 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8793 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008794
8795 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008796 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008797 ASSERT_TRUE(mDispatcher->waitForIdle());
8798 mWindow->assertNoEvents();
8799}
8800
8801/**
8802 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8803 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8804 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8805 * the ANR mechanism should still work.
8806 *
8807 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8808 * DOWN event, while not responding on the second one.
8809 */
8810TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8811 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008812 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008813 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8814 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8815 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008816 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008817
8818 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008819 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008820 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8821 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8822 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008823 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008824
8825 // We have now sent down and up. Let's consume first event and then ANR on the second.
8826 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8827 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008828 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008829}
8830
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008831// A spy window can receive an ANR
8832TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8833 sp<FakeWindowHandle> spy = addSpyWindow();
8834
8835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008837 WINDOW_LOCATION));
8838 mWindow->consumeMotionDown();
8839
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008840 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008841 ASSERT_TRUE(sequenceNum);
8842 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008843 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008844
8845 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008846 spy->consumeMotionEvent(
8847 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008848 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008849 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008850}
8851
8852// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008853// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008854TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8855 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008856
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008858 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008859 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008860 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008861
8862 // Stuck on the ACTION_UP
8863 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008864 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008865
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008866 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008867 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008868 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8869 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008870
8871 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8872 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008873 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008874 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008875 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008876}
8877
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008878// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008879// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008880TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8881 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008882
8883 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008884 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8885 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008886
8887 mWindow->consumeMotionDown();
8888 // Stuck on the ACTION_UP
8889 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008890 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008891
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008892 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008893 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008894 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8895 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008896
8897 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8898 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008899 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008900 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008901 spy->assertNoEvents();
8902}
8903
8904TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008905 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008906
Prabir Pradhanfb549072023-10-05 19:17:36 +00008907 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008908
8909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008910 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008911 WINDOW_LOCATION));
8912
8913 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8914 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8915 ASSERT_TRUE(consumeSeq);
8916
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008917 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8918 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008919
8920 monitor.finishEvent(*consumeSeq);
8921 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8922
8923 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008924 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008925}
8926
8927// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8928// process events, you don't get an anr. When the window later becomes unresponsive again, you
8929// get an ANR again.
8930// 1. tap -> block on ACTION_UP -> receive ANR
8931// 2. consume all pending events (= queue becomes healthy again)
8932// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8933TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8934 tapOnWindow();
8935
8936 mWindow->consumeMotionDown();
8937 // Block on ACTION_UP
8938 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008939 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008940 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8941 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008942 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008943 mWindow->assertNoEvents();
8944
8945 tapOnWindow();
8946 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008947 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008948 mWindow->consumeMotionUp();
8949
8950 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008951 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008952 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008953 mWindow->assertNoEvents();
8954}
8955
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008956// If a connection remains unresponsive for a while, make sure policy is only notified once about
8957// it.
8958TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008960 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008961 WINDOW_LOCATION));
8962
8963 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008964 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008965 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008966 // 'notifyConnectionUnresponsive' should only be called once per connection
8967 mFakePolicy->assertNotifyAnrWasNotCalled();
8968 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008969 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008970 mWindow->consumeMotionEvent(
8971 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008972 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008973 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008974 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008975 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008976}
8977
8978/**
8979 * 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 -07008980 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008981 */
8982TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008983 // The timeouts in this test are established by relying on the fact that the "key waiting for
8984 // events timeout" is equal to 500ms.
8985 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008986 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008987 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008988
8989 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008990 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008991 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008992 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008993 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008994
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008995 // Don't finish the events yet, and send a key
8996 mDispatcher->notifyKey(
8997 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8998 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8999 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009000 // Key will not be sent to the window, yet, because the window is still processing events
9001 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009002 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009003 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009004
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009005 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009006 // if we wait long enough though, dispatcher will give up, and still send the key
9007 // to the focused window, even though we have not yet finished the motion event
9008 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9009 mWindow->finishEvent(*downSequenceNum);
9010 mWindow->finishEvent(*upSequenceNum);
9011}
9012
9013/**
9014 * If a window is processing a motion event, and then a key event comes in, the key event should
9015 * not go to the focused window until the motion is processed.
9016 * If then a new motion comes in, then the pending key event should be going to the currently
9017 * focused window right away.
9018 */
9019TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009020 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
9021 // The timeouts in this test are established by relying on the fact that the "key waiting for
9022 // events timeout" is equal to 500ms.
9023 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009024 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009025 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009026
9027 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009028 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009029 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009030 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009031 ASSERT_TRUE(upSequenceNum);
9032 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009033 mDispatcher->notifyKey(
9034 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9035 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9036 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009037 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009038 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009039
9040 // Now tap down again. It should cause the pending key to go to the focused window right away.
9041 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009042 // Now that we tapped, we should receive the key immediately.
9043 // Since there's still room for slowness, we use 200ms, which is much less than
9044 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
9045 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
9046 ASSERT_NE(nullptr, keyEvent);
9047 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
9048 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
9049 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
9050 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009051 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
9052 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009053 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9054 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009055 mWindow->assertNoEvents();
9056}
9057
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009058/**
9059 * Send an event to the app and have the app not respond right away.
9060 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9061 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
9062 * At some point, the window becomes responsive again.
9063 * Ensure that subsequent events get dropped, and the next gesture is delivered.
9064 */
9065TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
9066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9067 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
9068 .build());
9069
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009070 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07009071 ASSERT_TRUE(sequenceNum);
9072 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9073 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9074
9075 mWindow->finishEvent(*sequenceNum);
9076 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
9077 ASSERT_TRUE(mDispatcher->waitForIdle());
9078 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
9079
9080 // Now that the window is responsive, let's continue the gesture.
9081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9082 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9083 .build());
9084
9085 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9086 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9087 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9088 .build());
9089
9090 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9091 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9092 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9093 .build());
9094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9095 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9096 .build());
9097 // We already canceled this pointer, so the window shouldn't get any new events.
9098 mWindow->assertNoEvents();
9099
9100 // Start another one.
9101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9102 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9103 .build());
9104 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9105}
9106
Prabir Pradhanfc364722024-02-08 17:51:20 +00009107// Send an event to the app and have the app not respond right away. Then remove the app window.
9108// When the window is removed, the dispatcher will cancel the events for that window.
9109// So InputDispatcher will enqueue ACTION_CANCEL event as well.
9110TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9111 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9112 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9113 {WINDOW_LOCATION}));
9114
9115 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9116 ASSERT_TRUE(sequenceNum);
9117
9118 // Remove the window, but the input channel should remain alive.
9119 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9120
9121 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9122 // Since the window was removed, Dispatcher does not know the PID associated with the window
9123 // anymore, so the policy is notified without the PID.
9124 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9125 /*pid=*/std::nullopt);
9126
9127 mWindow->finishEvent(*sequenceNum);
9128 // The cancellation was generated when the window was removed, along with the focus event.
9129 mWindow->consumeMotionEvent(
9130 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9131 mWindow->consumeFocusEvent(false);
9132 ASSERT_TRUE(mDispatcher->waitForIdle());
9133 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9134}
9135
9136// Send an event to the app and have the app not respond right away. Wait for the policy to be
9137// notified of the unresponsive window, then remove the app window.
9138TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9139 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9140 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9141 {WINDOW_LOCATION}));
9142
9143 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9144 ASSERT_TRUE(sequenceNum);
9145 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9146 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9147
9148 // Remove the window, but the input channel should remain alive.
9149 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9150
9151 mWindow->finishEvent(*sequenceNum);
9152 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9153 mWindow->consumeMotionEvent(
9154 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9155 mWindow->consumeFocusEvent(false);
9156 ASSERT_TRUE(mDispatcher->waitForIdle());
9157 // Since the window was removed, Dispatcher does not know the PID associated with the window
9158 // becoming responsive, so the policy is notified without the PID.
9159 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9160}
9161
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009162class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9163 virtual void SetUp() override {
9164 InputDispatcherTest::SetUp();
9165
Chris Yea209fde2020-07-22 13:54:51 -07009166 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009167 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009168 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9169 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009170 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009171 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009172 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009173
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009174 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9175 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009176 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009177 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009178
9179 // Set focused application.
9180 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009181 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009182
9183 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009184 mDispatcher->onWindowInfosChanged(
9185 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009186 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009187 mFocusedWindow->consumeFocusEvent(true);
9188 }
9189
9190 virtual void TearDown() override {
9191 InputDispatcherTest::TearDown();
9192
9193 mUnfocusedWindow.clear();
9194 mFocusedWindow.clear();
9195 }
9196
9197protected:
Chris Yea209fde2020-07-22 13:54:51 -07009198 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009199 sp<FakeWindowHandle> mUnfocusedWindow;
9200 sp<FakeWindowHandle> mFocusedWindow;
9201 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9202 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9203 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9204
9205 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9206
9207 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9208
9209private:
9210 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009212 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009213 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009215 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009216 location));
9217 }
9218};
9219
9220// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9221// should be ANR'd first.
9222TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009224 injectMotionEvent(*mDispatcher,
9225 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9226 AINPUT_SOURCE_TOUCHSCREEN)
9227 .pointer(PointerBuilder(0, ToolType::FINGER)
9228 .x(FOCUSED_WINDOW_LOCATION.x)
9229 .y(FOCUSED_WINDOW_LOCATION.y))
9230 .build()));
9231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9232 injectMotionEvent(*mDispatcher,
9233 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9234 AINPUT_SOURCE_TOUCHSCREEN)
9235 .pointer(PointerBuilder(0, ToolType::FINGER)
9236 .x(FOCUSED_WINDOW_LOCATION.x)
9237 .y(FOCUSED_WINDOW_LOCATION.y))
9238 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009239 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009240 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009241 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009242 // We consumed all events, so no ANR
9243 ASSERT_TRUE(mDispatcher->waitForIdle());
9244 mFakePolicy->assertNotifyAnrWasNotCalled();
9245
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009247 injectMotionEvent(*mDispatcher,
9248 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9249 AINPUT_SOURCE_TOUCHSCREEN)
9250 .pointer(PointerBuilder(0, ToolType::FINGER)
9251 .x(FOCUSED_WINDOW_LOCATION.x)
9252 .y(FOCUSED_WINDOW_LOCATION.y))
9253 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009254 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009255 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009256
9257 const std::chrono::duration timeout =
9258 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009259 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009260
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009261 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009262 mFocusedWindow->consumeMotionDown();
9263 // This cancel is generated because the connection was unresponsive
9264 mFocusedWindow->consumeMotionCancel();
9265 mFocusedWindow->assertNoEvents();
9266 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009267 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009268 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9269 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009270 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009271}
9272
9273// If we have 2 windows with identical timeouts that are both unresponsive,
9274// it doesn't matter which order they should have ANR.
9275// But we should receive ANR for both.
9276TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9277 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009278 mUnfocusedWindow->setDispatchingTimeout(
9279 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009280 mDispatcher->onWindowInfosChanged(
9281 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009282
9283 tapOnFocusedWindow();
9284 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009285 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009286 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9287 mFocusedWindow->getDispatchingTimeout(
9288 DISPATCHING_TIMEOUT)),
9289 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9290
9291 ASSERT_THAT(anrConnectionTokens,
9292 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9293 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009294
9295 ASSERT_TRUE(mDispatcher->waitForIdle());
9296 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009297
9298 mFocusedWindow->consumeMotionDown();
9299 mFocusedWindow->consumeMotionUp();
9300 mUnfocusedWindow->consumeMotionOutside();
9301
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009302 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9303 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009304
9305 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009306 ASSERT_THAT(responsiveTokens,
9307 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9308 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009309 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009310}
9311
9312// If a window is already not responding, the second tap on the same window should be ignored.
9313// We should also log an error to account for the dropped event (not tested here).
9314// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9315TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9316 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009317 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009318 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009319 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009320 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009321 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009322 ASSERT_TRUE(upEventSequenceNum);
9323 const std::chrono::duration timeout =
9324 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009325 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009326
9327 // Tap once again
9328 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009329 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009330 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009331 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009332 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009333 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009334 FOCUSED_WINDOW_LOCATION));
9335 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9336 // valid touch target
9337 mUnfocusedWindow->assertNoEvents();
9338
9339 // Consume the first tap
9340 mFocusedWindow->finishEvent(*downEventSequenceNum);
9341 mFocusedWindow->finishEvent(*upEventSequenceNum);
9342 ASSERT_TRUE(mDispatcher->waitForIdle());
9343 // The second tap did not go to the focused window
9344 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009345 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009346 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9347 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009348 mFakePolicy->assertNotifyAnrWasNotCalled();
9349}
9350
9351// If you tap outside of all windows, there will not be ANR
9352TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009353 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009355 LOCATION_OUTSIDE_ALL_WINDOWS));
9356 ASSERT_TRUE(mDispatcher->waitForIdle());
9357 mFakePolicy->assertNotifyAnrWasNotCalled();
9358}
9359
9360// Since the focused window is paused, tapping on it should not produce any events
9361TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9362 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009363 mDispatcher->onWindowInfosChanged(
9364 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009365
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009366 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009367 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009368 FOCUSED_WINDOW_LOCATION));
9369
9370 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9371 ASSERT_TRUE(mDispatcher->waitForIdle());
9372 // Should not ANR because the window is paused, and touches shouldn't go to it
9373 mFakePolicy->assertNotifyAnrWasNotCalled();
9374
9375 mFocusedWindow->assertNoEvents();
9376 mUnfocusedWindow->assertNoEvents();
9377}
9378
9379/**
9380 * 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 -07009381 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009382 * If a different window becomes focused at this time, the key should go to that window instead.
9383 *
9384 * Warning!!!
9385 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9386 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009387 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009388 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9389 *
9390 * If that value changes, this test should also change.
9391 */
9392TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9393 // Set a long ANR timeout to prevent it from triggering
9394 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009395 mDispatcher->onWindowInfosChanged(
9396 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009397
9398 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009399 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009400 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009401 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009402 ASSERT_TRUE(upSequenceNum);
9403 // Don't finish the events yet, and send a key
9404 // Injection will succeed because we will eventually give up and send the key to the focused
9405 // window even if motions are still being processed.
9406
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009407 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009408 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9409 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009411 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009412 // and the key remains pending, waiting for the touch events to be processed.
9413 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9414 // under the hood.
9415 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9416 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009417
9418 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009419 mFocusedWindow->setFocusable(false);
9420 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009421 mDispatcher->onWindowInfosChanged(
9422 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009423 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009424
9425 // Focus events should precede the key events
9426 mUnfocusedWindow->consumeFocusEvent(true);
9427 mFocusedWindow->consumeFocusEvent(false);
9428
9429 // Finish the tap events, which should unblock dispatcher
9430 mUnfocusedWindow->finishEvent(*downSequenceNum);
9431 mUnfocusedWindow->finishEvent(*upSequenceNum);
9432
9433 // Now that all queues are cleared and no backlog in the connections, the key event
9434 // can finally go to the newly focused "mUnfocusedWindow".
9435 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9436 mFocusedWindow->assertNoEvents();
9437 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009438 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009439}
9440
9441// When the touch stream is split across 2 windows, and one of them does not respond,
9442// then ANR should be raised and the touch should be canceled for the unresponsive window.
9443// The other window should not be affected by that.
9444TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9445 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009446 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9447 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9448 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009449 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009450
9451 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009452 mDispatcher->notifyMotion(
9453 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9454 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009455
9456 const std::chrono::duration timeout =
9457 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009458 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009459
9460 mUnfocusedWindow->consumeMotionDown();
9461 mFocusedWindow->consumeMotionDown();
9462 // Focused window may or may not receive ACTION_MOVE
9463 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009464 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009465 ASSERT_TRUE(moveOrCancelSequenceNum);
9466 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9467 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009468 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009469 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9470 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9471 mFocusedWindow->consumeMotionCancel();
9472 } else {
9473 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9474 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009475 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009476 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9477 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009478
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009479 mUnfocusedWindow->assertNoEvents();
9480 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009481 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009482}
9483
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009484/**
9485 * If we have no focused window, and a key comes in, we start the ANR timer.
9486 * The focused application should add a focused window before the timer runs out to prevent ANR.
9487 *
9488 * If the user touches another application during this time, the key should be dropped.
9489 * Next, if a new focused window comes in, without toggling the focused application,
9490 * then no ANR should occur.
9491 *
9492 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9493 * but in some cases the policy may not update the focused application.
9494 */
9495TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9496 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9497 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009498 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009499 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9500 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9501 mFocusedWindow->setFocusable(false);
9502
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009503 mDispatcher->onWindowInfosChanged(
9504 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009505 mFocusedWindow->consumeFocusEvent(false);
9506
9507 // Send a key. The ANR timer should start because there is no focused window.
9508 // 'focusedApplication' will get blamed if this timer completes.
9509 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009510 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009511 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9512 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009513 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009515
9516 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9517 // then the injected touches won't cause the focused event to get dropped.
9518 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9519 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9520 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9521 // For this test, it means that the key would get delivered to the window once it becomes
9522 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009523 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009524
9525 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009526 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9527 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9528 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009529
9530 // We do not consume the motion right away, because that would require dispatcher to first
9531 // process (== drop) the key event, and by that time, ANR will be raised.
9532 // Set the focused window first.
9533 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009534 mDispatcher->onWindowInfosChanged(
9535 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009536 setFocusedWindow(mFocusedWindow);
9537 mFocusedWindow->consumeFocusEvent(true);
9538 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9539 // to another application. This could be a bug / behaviour in the policy.
9540
9541 mUnfocusedWindow->consumeMotionDown();
9542
9543 ASSERT_TRUE(mDispatcher->waitForIdle());
9544 // Should not ANR because we actually have a focused window. It was just added too slowly.
9545 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9546}
9547
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009548/**
9549 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9550 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9551 * dispatcher doesn't prune pointer events incorrectly.
9552 *
9553 * This test reproduces a crash in InputDispatcher.
9554 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9555 *
9556 * Keep the currently focused application (mApplication), and have no focused window.
9557 * We set up two additional windows:
9558 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9559 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9560 * window. This window is not focusable, but is touchable.
9561 *
9562 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9563 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9564 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9565 *
9566 * Now, we touch "Another window". This window is owned by a different application than
9567 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9568 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9569 * dropping the events from its queue. Ensure that no crash occurs.
9570 *
9571 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9572 * This does not affect the test running time.
9573 */
9574TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9575 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9576 std::make_shared<FakeApplicationHandle>();
9577 systemUiApplication->setDispatchingTimeout(3000ms);
9578 mFakePolicy->setStaleEventTimeout(3000ms);
9579 sp<FakeWindowHandle> navigationBar =
9580 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9581 ADISPLAY_ID_DEFAULT);
9582 navigationBar->setFocusable(false);
9583 navigationBar->setWatchOutsideTouch(true);
9584 navigationBar->setFrame(Rect(0, 0, 100, 100));
9585
9586 mApplication->setDispatchingTimeout(3000ms);
9587 // 'mApplication' is already focused, but we call it again here to make it explicit.
9588 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9589
9590 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9591 std::make_shared<FakeApplicationHandle>();
9592 sp<FakeWindowHandle> appWindow =
9593 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9594 ADISPLAY_ID_DEFAULT);
9595 appWindow->setFocusable(false);
9596 appWindow->setFrame(Rect(100, 100, 200, 200));
9597
9598 mDispatcher->onWindowInfosChanged(
9599 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9600 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9601 mFocusedWindow->consumeFocusEvent(false);
9602
9603 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9604 // in response.
9605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9606 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9607 .build());
9608 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9609
9610 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9611 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9612 InputEventInjectionResult result =
9613 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9614 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9615 /*allowKeyRepeat=*/false);
9616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9617
9618 // Finish the gesture - lift up finger and inject ACTION_UP key event
9619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9620 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9621 .build());
9622 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9623 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9624 /*allowKeyRepeat=*/false);
9625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9626 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9627 // getting any events yet.
9628 navigationBar->assertNoEvents();
9629
9630 // Now touch "Another window". This touch is going to a different application than the one we
9631 // are waiting for (which is 'mApplication').
9632 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9633 // trying to be injected) and to continue processing the rest of the events in the original
9634 // order.
9635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9636 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9637 .build());
9638 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9639 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9640 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9641
9642 appWindow->assertNoEvents();
9643 navigationBar->assertNoEvents();
9644}
9645
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009646// These tests ensure we cannot send touch events to a window that's positioned behind a window
9647// that has feature NO_INPUT_CHANNEL.
9648// Layout:
9649// Top (closest to user)
9650// mNoInputWindow (above all windows)
9651// mBottomWindow
9652// Bottom (furthest from user)
9653class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9654 virtual void SetUp() override {
9655 InputDispatcherTest::SetUp();
9656
9657 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009658 mNoInputWindow =
9659 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9660 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009661 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009662 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009663 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9664 // It's perfectly valid for this window to not have an associated input channel
9665
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009666 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9667 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009668 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9669
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009670 mDispatcher->onWindowInfosChanged(
9671 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009672 }
9673
9674protected:
9675 std::shared_ptr<FakeApplicationHandle> mApplication;
9676 sp<FakeWindowHandle> mNoInputWindow;
9677 sp<FakeWindowHandle> mBottomWindow;
9678};
9679
9680TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9681 PointF touchedPoint = {10, 10};
9682
Prabir Pradhan678438e2023-04-13 19:32:51 +00009683 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9684 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9685 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009686
9687 mNoInputWindow->assertNoEvents();
9688 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9689 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9690 // and therefore should prevent mBottomWindow from receiving touches
9691 mBottomWindow->assertNoEvents();
9692}
9693
9694/**
9695 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9696 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9697 */
9698TEST_F(InputDispatcherMultiWindowOcclusionTests,
9699 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009700 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9701 "Window with input channel and NO_INPUT_CHANNEL",
9702 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009703
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009704 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009705 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009706 mDispatcher->onWindowInfosChanged(
9707 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009708
9709 PointF touchedPoint = {10, 10};
9710
Prabir Pradhan678438e2023-04-13 19:32:51 +00009711 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9712 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9713 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009714
9715 mNoInputWindow->assertNoEvents();
9716 mBottomWindow->assertNoEvents();
9717}
9718
Vishnu Nair958da932020-08-21 17:12:37 -07009719class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9720protected:
9721 std::shared_ptr<FakeApplicationHandle> mApp;
9722 sp<FakeWindowHandle> mWindow;
9723 sp<FakeWindowHandle> mMirror;
9724
9725 virtual void SetUp() override {
9726 InputDispatcherTest::SetUp();
9727 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009728 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009729 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009730 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9731 mWindow->setFocusable(true);
9732 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009733 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009734 }
9735};
9736
9737TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9738 // Request focus on a mirrored window
9739 setFocusedWindow(mMirror);
9740
9741 // window gets focused
9742 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009744 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009745 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9746}
9747
9748// A focused & mirrored window remains focused only if the window and its mirror are both
9749// focusable.
9750TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9751 setFocusedWindow(mMirror);
9752
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009753 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009754 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009757 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009759 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009760 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9761
9762 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009763 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009764
9765 // window loses focus since one of the windows associated with the token in not focusable
9766 mWindow->consumeFocusEvent(false);
9767
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009768 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009769 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009770 mWindow->assertNoEvents();
9771}
9772
9773// A focused & mirrored window remains focused until the window and its mirror both become
9774// invisible.
9775TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9776 setFocusedWindow(mMirror);
9777
9778 // window gets focused
9779 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009781 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009782 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009784 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009785 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9786
9787 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009788 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009789
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009792 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009794 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009795 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9796
9797 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009798 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009799
9800 // window loses focus only after all windows associated with the token become invisible.
9801 mWindow->consumeFocusEvent(false);
9802
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009803 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009804 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009805 mWindow->assertNoEvents();
9806}
9807
9808// A focused & mirrored window remains focused until both windows are removed.
9809TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9810 setFocusedWindow(mMirror);
9811
9812 // window gets focused
9813 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009815 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009816 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009818 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009819 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9820
9821 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009822 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009823
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009825 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009826 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009828 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009829 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009830
9831 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009832 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009833 mWindow->consumeFocusEvent(false);
9834
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009835 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009836 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009837 mWindow->assertNoEvents();
9838}
9839
9840// Focus request can be pending until one window becomes visible.
9841TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9842 // Request focus on an invisible mirror.
9843 mWindow->setVisible(false);
9844 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009845 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009846 setFocusedWindow(mMirror);
9847
9848 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009850 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9851 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009852
9853 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009854 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009855
9856 // window gets focused
9857 mWindow->consumeFocusEvent(true);
9858 // window gets the pending key event
9859 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9860}
Prabir Pradhan99987712020-11-10 18:43:05 -08009861
9862class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9863protected:
9864 std::shared_ptr<FakeApplicationHandle> mApp;
9865 sp<FakeWindowHandle> mWindow;
9866 sp<FakeWindowHandle> mSecondWindow;
9867
9868 void SetUp() override {
9869 InputDispatcherTest::SetUp();
9870 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009871 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009872 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009873 mSecondWindow =
9874 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009875 mSecondWindow->setFocusable(true);
9876
9877 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009878 mDispatcher->onWindowInfosChanged(
9879 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009880
9881 setFocusedWindow(mWindow);
9882 mWindow->consumeFocusEvent(true);
9883 }
9884
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009885 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009886 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009887 }
9888
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009889 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9890 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009891 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009892 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9893 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009894 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009895 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009896 }
9897};
9898
9899TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9900 // Ensure that capture cannot be obtained for unfocused windows.
9901 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9902 mFakePolicy->assertSetPointerCaptureNotCalled();
9903 mSecondWindow->assertNoEvents();
9904
9905 // Ensure that capture can be enabled from the focus window.
9906 requestAndVerifyPointerCapture(mWindow, true);
9907
9908 // Ensure that capture cannot be disabled from a window that does not have capture.
9909 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9910 mFakePolicy->assertSetPointerCaptureNotCalled();
9911
9912 // Ensure that capture can be disabled from the window with capture.
9913 requestAndVerifyPointerCapture(mWindow, false);
9914}
9915
9916TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009917 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009918
9919 setFocusedWindow(mSecondWindow);
9920
9921 // Ensure that the capture disabled event was sent first.
9922 mWindow->consumeCaptureEvent(false);
9923 mWindow->consumeFocusEvent(false);
9924 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009925 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009926
9927 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009928 notifyPointerCaptureChanged({});
9929 notifyPointerCaptureChanged(request);
9930 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009931 mWindow->assertNoEvents();
9932 mSecondWindow->assertNoEvents();
9933 mFakePolicy->assertSetPointerCaptureNotCalled();
9934}
9935
9936TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009937 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009938
9939 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009940 notifyPointerCaptureChanged({});
9941 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009942
9943 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009944 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009945 mWindow->consumeCaptureEvent(false);
9946 mWindow->assertNoEvents();
9947}
9948
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009949TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9950 requestAndVerifyPointerCapture(mWindow, true);
9951
9952 // The first window loses focus.
9953 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009954 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009955 mWindow->consumeCaptureEvent(false);
9956
9957 // Request Pointer Capture from the second window before the notification from InputReader
9958 // arrives.
9959 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009960 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009961
9962 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009963 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009964
9965 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009966 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009967
9968 mSecondWindow->consumeFocusEvent(true);
9969 mSecondWindow->consumeCaptureEvent(true);
9970}
9971
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009972TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9973 // App repeatedly enables and disables capture.
9974 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9975 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9976 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9977 mFakePolicy->assertSetPointerCaptureCalled(false);
9978 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9979 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9980
9981 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9982 // first request is now stale, this should do nothing.
9983 notifyPointerCaptureChanged(firstRequest);
9984 mWindow->assertNoEvents();
9985
9986 // InputReader notifies that the second request was enabled.
9987 notifyPointerCaptureChanged(secondRequest);
9988 mWindow->consumeCaptureEvent(true);
9989}
9990
Prabir Pradhan7092e262022-05-03 16:51:09 +00009991TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9992 requestAndVerifyPointerCapture(mWindow, true);
9993
9994 // App toggles pointer capture off and on.
9995 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9996 mFakePolicy->assertSetPointerCaptureCalled(false);
9997
9998 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9999 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
10000
10001 // InputReader notifies that the latest "enable" request was processed, while skipping over the
10002 // preceding "disable" request.
10003 notifyPointerCaptureChanged(enableRequest);
10004
10005 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
10006 // any notifications.
10007 mWindow->assertNoEvents();
10008}
10009
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010010/**
10011 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
10012 * mouse movements don't affect the previous mouse hovering state.
10013 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
10014 * HOVER_MOVE events).
10015 */
10016TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
10017 // Mouse hover on the window
10018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
10019 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10020 .build());
10021 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10022 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
10023 .build());
10024
10025 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
10026 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
10027
10028 // Start pointer capture
10029 requestAndVerifyPointerCapture(mWindow, true);
10030
10031 // Send some relative mouse movements and receive them in the window.
10032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
10033 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
10034 .build());
10035 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
10036 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
10037
10038 // Stop pointer capture
10039 requestAndVerifyPointerCapture(mWindow, false);
10040
10041 // Continue hovering on the window
10042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
10043 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
10044 .build());
10045 mWindow->consumeMotionEvent(
10046 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
10047
10048 mWindow->assertNoEvents();
10049}
10050
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010051class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
10052protected:
10053 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000010054
10055 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
10056 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
10057
10058 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
10059 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10060
10061 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
10062 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
10063 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
10064 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
10065 MAXIMUM_OBSCURING_OPACITY);
10066
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010067 static constexpr gui::Uid TOUCHED_APP_UID{10001};
10068 static constexpr gui::Uid APP_B_UID{10002};
10069 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010070
10071 sp<FakeWindowHandle> mTouchWindow;
10072
10073 virtual void SetUp() override {
10074 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010075 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010076 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
10077 }
10078
10079 virtual void TearDown() override {
10080 InputDispatcherTest::TearDown();
10081 mTouchWindow.clear();
10082 }
10083
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010084 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050010085 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010086 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010087 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010088 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010089 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010090 return window;
10091 }
10092
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010093 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010094 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
10095 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010096 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010097 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010098 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010099 return window;
10100 }
10101
10102 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010103 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10104 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10105 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010106 }
10107};
10108
10109TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010110 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010111 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010112 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010113
10114 touch();
10115
10116 mTouchWindow->assertNoEvents();
10117}
10118
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010119TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000010120 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
10121 const sp<FakeWindowHandle>& w =
10122 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010123 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010124
10125 touch();
10126
10127 mTouchWindow->assertNoEvents();
10128}
10129
10130TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010131 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
10132 const sp<FakeWindowHandle>& w =
10133 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010134 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010135
10136 touch();
10137
10138 w->assertNoEvents();
10139}
10140
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010141TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010142 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010143 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010144
10145 touch();
10146
10147 mTouchWindow->consumeAnyMotionDown();
10148}
10149
10150TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010151 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010152 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010153 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010154 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010155
10156 touch({PointF{100, 100}});
10157
10158 mTouchWindow->consumeAnyMotionDown();
10159}
10160
10161TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010162 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010163 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010164 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010165
10166 touch();
10167
10168 mTouchWindow->consumeAnyMotionDown();
10169}
10170
10171TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10172 const sp<FakeWindowHandle>& w =
10173 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010174 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010175
10176 touch();
10177
10178 mTouchWindow->consumeAnyMotionDown();
10179}
10180
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010181TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10182 const sp<FakeWindowHandle>& w =
10183 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010185
10186 touch();
10187
10188 w->assertNoEvents();
10189}
10190
10191/**
10192 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10193 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10194 * window, the occluding window will still receive ACTION_OUTSIDE event.
10195 */
10196TEST_F(InputDispatcherUntrustedTouchesTest,
10197 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10198 const sp<FakeWindowHandle>& w =
10199 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010200 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010201 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010202
10203 touch();
10204
10205 w->consumeMotionOutside();
10206}
10207
10208TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10209 const sp<FakeWindowHandle>& w =
10210 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010211 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010212 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010213
10214 touch();
10215
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010216 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010217}
10218
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010219TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010220 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010221 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10222 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010223 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010224
10225 touch();
10226
10227 mTouchWindow->consumeAnyMotionDown();
10228}
10229
10230TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10231 const sp<FakeWindowHandle>& w =
10232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10233 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010234 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010235
10236 touch();
10237
10238 mTouchWindow->consumeAnyMotionDown();
10239}
10240
10241TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010242 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010243 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10244 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010245 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010246
10247 touch();
10248
10249 mTouchWindow->assertNoEvents();
10250}
10251
10252TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10253 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10254 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010255 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10256 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010257 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010258 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10259 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010260 mDispatcher->onWindowInfosChanged(
10261 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010262
10263 touch();
10264
10265 mTouchWindow->assertNoEvents();
10266}
10267
10268TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10269 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10270 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010271 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10272 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010273 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010274 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10275 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010276 mDispatcher->onWindowInfosChanged(
10277 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010278
10279 touch();
10280
10281 mTouchWindow->consumeAnyMotionDown();
10282}
10283
10284TEST_F(InputDispatcherUntrustedTouchesTest,
10285 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10286 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010287 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10288 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010289 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010290 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10291 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010292 mDispatcher->onWindowInfosChanged(
10293 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010294
10295 touch();
10296
10297 mTouchWindow->consumeAnyMotionDown();
10298}
10299
10300TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10301 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010302 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10303 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010304 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010305 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10306 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010307 mDispatcher->onWindowInfosChanged(
10308 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010309
10310 touch();
10311
10312 mTouchWindow->assertNoEvents();
10313}
10314
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010315TEST_F(InputDispatcherUntrustedTouchesTest,
10316 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10317 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010318 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10319 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010320 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010321 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10322 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010323 mDispatcher->onWindowInfosChanged(
10324 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010325
10326 touch();
10327
10328 mTouchWindow->assertNoEvents();
10329}
10330
10331TEST_F(InputDispatcherUntrustedTouchesTest,
10332 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10333 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010334 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10335 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010336 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010337 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10338 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010339 mDispatcher->onWindowInfosChanged(
10340 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010341
10342 touch();
10343
10344 mTouchWindow->consumeAnyMotionDown();
10345}
10346
10347TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10348 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010349 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10350 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010351 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010352
10353 touch();
10354
10355 mTouchWindow->consumeAnyMotionDown();
10356}
10357
10358TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10359 const sp<FakeWindowHandle>& w =
10360 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010361 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010362
10363 touch();
10364
10365 mTouchWindow->consumeAnyMotionDown();
10366}
10367
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010368TEST_F(InputDispatcherUntrustedTouchesTest,
10369 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10370 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10371 const sp<FakeWindowHandle>& w =
10372 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010373 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010374
10375 touch();
10376
10377 mTouchWindow->assertNoEvents();
10378}
10379
10380TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10381 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10382 const sp<FakeWindowHandle>& w =
10383 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010384 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010385
10386 touch();
10387
10388 mTouchWindow->consumeAnyMotionDown();
10389}
10390
10391TEST_F(InputDispatcherUntrustedTouchesTest,
10392 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10393 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10394 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010395 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10396 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010397 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010398
10399 touch();
10400
10401 mTouchWindow->consumeAnyMotionDown();
10402}
10403
10404TEST_F(InputDispatcherUntrustedTouchesTest,
10405 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10406 const sp<FakeWindowHandle>& w1 =
10407 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10408 OPACITY_BELOW_THRESHOLD);
10409 const sp<FakeWindowHandle>& w2 =
10410 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10411 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010412 mDispatcher->onWindowInfosChanged(
10413 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010414
10415 touch();
10416
10417 mTouchWindow->assertNoEvents();
10418}
10419
10420/**
10421 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10422 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10423 * (which alone would result in allowing touches) does not affect the blocking behavior.
10424 */
10425TEST_F(InputDispatcherUntrustedTouchesTest,
10426 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10427 const sp<FakeWindowHandle>& wB =
10428 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10429 OPACITY_BELOW_THRESHOLD);
10430 const sp<FakeWindowHandle>& wC =
10431 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10432 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010433 mDispatcher->onWindowInfosChanged(
10434 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010435
10436 touch();
10437
10438 mTouchWindow->assertNoEvents();
10439}
10440
10441/**
10442 * This test is testing that a window from a different UID but with same application token doesn't
10443 * block the touch. Apps can share the application token for close UI collaboration for example.
10444 */
10445TEST_F(InputDispatcherUntrustedTouchesTest,
10446 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10447 const sp<FakeWindowHandle>& w =
10448 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10449 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010450 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010451
10452 touch();
10453
10454 mTouchWindow->consumeAnyMotionDown();
10455}
10456
arthurhungb89ccb02020-12-30 16:19:01 +080010457class InputDispatcherDragTests : public InputDispatcherTest {
10458protected:
10459 std::shared_ptr<FakeApplicationHandle> mApp;
10460 sp<FakeWindowHandle> mWindow;
10461 sp<FakeWindowHandle> mSecondWindow;
10462 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010463 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010464 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10465 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010466
10467 void SetUp() override {
10468 InputDispatcherTest::SetUp();
10469 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010470 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010471 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010472
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010473 mSecondWindow =
10474 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010475 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010476
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010477 mSpyWindow =
10478 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010479 mSpyWindow->setSpy(true);
10480 mSpyWindow->setTrustedOverlay(true);
10481 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10482
arthurhungb89ccb02020-12-30 16:19:01 +080010483 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010484 mDispatcher->onWindowInfosChanged(
10485 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10486 {},
10487 0,
10488 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010489 }
10490
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010491 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10492 switch (fromSource) {
10493 case AINPUT_SOURCE_TOUCHSCREEN:
10494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010495 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010496 ADISPLAY_ID_DEFAULT, {50, 50}))
10497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10498 break;
10499 case AINPUT_SOURCE_STYLUS:
10500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010501 injectMotionEvent(*mDispatcher,
10502 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10503 AINPUT_SOURCE_STYLUS)
10504 .buttonState(
10505 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10506 .pointer(PointerBuilder(0, ToolType::STYLUS)
10507 .x(50)
10508 .y(50))
10509 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010510 break;
10511 case AINPUT_SOURCE_MOUSE:
10512 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010513 injectMotionEvent(*mDispatcher,
10514 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10515 AINPUT_SOURCE_MOUSE)
10516 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10517 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10518 ToolType::MOUSE)
10519 .x(50)
10520 .y(50))
10521 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010522 break;
10523 default:
10524 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10525 }
arthurhungb89ccb02020-12-30 16:19:01 +080010526
10527 // Window should receive motion event.
10528 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010529 // Spy window should also receive motion event
10530 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010531 }
10532
10533 // Start performing drag, we will create a drag window and transfer touch to it.
10534 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10535 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010536 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010537 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010538 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010539 }
arthurhungb89ccb02020-12-30 16:19:01 +080010540
10541 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010542 mDragWindow =
10543 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010544 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010545 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10546 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10547 {},
10548 0,
10549 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010550
10551 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010552 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010553 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10554 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010555 if (transferred) {
10556 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010557 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010558 }
10559 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010560 }
10561};
10562
10563TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010564 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010565
10566 // Move on window.
10567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010568 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010569 ADISPLAY_ID_DEFAULT, {50, 50}))
10570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010571 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010572 mWindow->consumeDragEvent(false, 50, 50);
10573 mSecondWindow->assertNoEvents();
10574
10575 // Move to another window.
10576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010577 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010578 ADISPLAY_ID_DEFAULT, {150, 50}))
10579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010580 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010581 mWindow->consumeDragEvent(true, 150, 50);
10582 mSecondWindow->consumeDragEvent(false, 50, 50);
10583
10584 // Move back to original window.
10585 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010586 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010587 ADISPLAY_ID_DEFAULT, {50, 50}))
10588 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010589 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010590 mWindow->consumeDragEvent(false, 50, 50);
10591 mSecondWindow->consumeDragEvent(true, -50, 50);
10592
10593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010594 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10595 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010597 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010598 mWindow->assertNoEvents();
10599 mSecondWindow->assertNoEvents();
10600}
10601
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010602TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010603 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010604
10605 // No cancel event after drag start
10606 mSpyWindow->assertNoEvents();
10607
10608 const MotionEvent secondFingerDownEvent =
10609 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10610 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010611 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10612 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010613 .build();
10614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010615 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010616 InputEventInjectionSync::WAIT_FOR_RESULT))
10617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10618
10619 // Receives cancel for first pointer after next pointer down
10620 mSpyWindow->consumeMotionCancel();
10621 mSpyWindow->consumeMotionDown();
10622
10623 mSpyWindow->assertNoEvents();
10624}
10625
arthurhungf452d0b2021-01-06 00:19:52 +080010626TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010627 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010628
10629 // Move on window.
10630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010631 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010632 ADISPLAY_ID_DEFAULT, {50, 50}))
10633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010634 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010635 mWindow->consumeDragEvent(false, 50, 50);
10636 mSecondWindow->assertNoEvents();
10637
10638 // Move to another window.
10639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010640 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010641 ADISPLAY_ID_DEFAULT, {150, 50}))
10642 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010643 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010644 mWindow->consumeDragEvent(true, 150, 50);
10645 mSecondWindow->consumeDragEvent(false, 50, 50);
10646
10647 // drop to another window.
10648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010649 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010650 {150, 50}))
10651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010652 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010653 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010654 mWindow->assertNoEvents();
10655 mSecondWindow->assertNoEvents();
10656}
10657
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010658TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10659 startDrag();
10660
10661 // No cancel event after drag start
10662 mSpyWindow->assertNoEvents();
10663
10664 const MotionEvent secondFingerDownEvent =
10665 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10666 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10667 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10668 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10669 .build();
10670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10671 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10672 InputEventInjectionSync::WAIT_FOR_RESULT))
10673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10674
10675 // Receives cancel for first pointer after next pointer down
10676 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010677 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010678 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10679
10680 mSpyWindow->assertNoEvents();
10681
10682 // Spy window calls pilfer pointers
10683 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10684 mDragWindow->assertNoEvents();
10685
10686 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010687 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010688 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10689 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10690 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10691 .build();
10692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010693 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010694 InputEventInjectionSync::WAIT_FOR_RESULT))
10695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10696
10697 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010698 mDragWindow->consumeMotionEvent(
10699 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010700 mDragWindow->assertNoEvents();
10701}
10702
arthurhung6d4bed92021-03-17 11:59:33 +080010703TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010704 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010705
10706 // Move on window and keep button pressed.
10707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010708 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010709 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10710 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010711 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010712 .build()))
10713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010714 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010715 mWindow->consumeDragEvent(false, 50, 50);
10716 mSecondWindow->assertNoEvents();
10717
10718 // Move to another window and release button, expect to drop item.
10719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010720 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010721 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10722 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010723 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010724 .build()))
10725 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010726 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010727 mWindow->assertNoEvents();
10728 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010729 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010730
10731 // nothing to the window.
10732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010733 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010734 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10735 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010736 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010737 .build()))
10738 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010739 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010740 mWindow->assertNoEvents();
10741 mSecondWindow->assertNoEvents();
10742}
10743
Arthur Hung54745652022-04-20 07:17:41 +000010744TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010745 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010746
10747 // Set second window invisible.
10748 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010749 mDispatcher->onWindowInfosChanged(
10750 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010751
10752 // Move on window.
10753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010754 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010755 ADISPLAY_ID_DEFAULT, {50, 50}))
10756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010757 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010758 mWindow->consumeDragEvent(false, 50, 50);
10759 mSecondWindow->assertNoEvents();
10760
10761 // Move to another window.
10762 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010764 ADISPLAY_ID_DEFAULT, {150, 50}))
10765 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010766 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010767 mWindow->consumeDragEvent(true, 150, 50);
10768 mSecondWindow->assertNoEvents();
10769
10770 // drop to another window.
10771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010772 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010773 {150, 50}))
10774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010775 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010776 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010777 mWindow->assertNoEvents();
10778 mSecondWindow->assertNoEvents();
10779}
10780
Arthur Hung54745652022-04-20 07:17:41 +000010781TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010782 // Ensure window could track pointerIds if it didn't support split touch.
10783 mWindow->setPreventSplitting(true);
10784
Arthur Hung54745652022-04-20 07:17:41 +000010785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010787 {50, 50}))
10788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10789 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10790
10791 const MotionEvent secondFingerDownEvent =
10792 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10793 .displayId(ADISPLAY_ID_DEFAULT)
10794 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010795 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10796 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010797 .build();
10798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010799 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010800 InputEventInjectionSync::WAIT_FOR_RESULT))
10801 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010802 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010803
10804 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010805 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010806}
10807
10808TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10809 // First down on second window.
10810 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010811 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010812 {150, 50}))
10813 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10814
10815 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10816
10817 // Second down on first window.
10818 const MotionEvent secondFingerDownEvent =
10819 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10820 .displayId(ADISPLAY_ID_DEFAULT)
10821 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010822 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10823 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010824 .build();
10825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010826 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010827 InputEventInjectionSync::WAIT_FOR_RESULT))
10828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10829 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010830 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010831
10832 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010833 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010834
10835 // Move on window.
10836 const MotionEvent secondFingerMoveEvent =
10837 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10838 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010839 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10840 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010841 .build();
10842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010843 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010844 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010845 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010846 mWindow->consumeDragEvent(false, 50, 50);
10847 mSecondWindow->consumeMotionMove();
10848
10849 // Release the drag pointer should perform drop.
10850 const MotionEvent secondFingerUpEvent =
10851 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10852 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010853 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10854 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010855 .build();
10856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010857 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010858 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010859 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010860 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010861 mWindow->assertNoEvents();
10862 mSecondWindow->consumeMotionMove();
10863}
10864
Arthur Hung3915c1f2022-05-31 07:17:17 +000010865TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010866 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010867
10868 // Update window of second display.
10869 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010870 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010871 mDispatcher->onWindowInfosChanged(
10872 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10873 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10874 {},
10875 0,
10876 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010877
10878 // Let second display has a touch state.
10879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010880 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010881 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10882 AINPUT_SOURCE_TOUCHSCREEN)
10883 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010884 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010885 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010886 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010887 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010888 mDispatcher->onWindowInfosChanged(
10889 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10890 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10891 {},
10892 0,
10893 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010894
10895 // Move on window.
10896 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010897 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010898 ADISPLAY_ID_DEFAULT, {50, 50}))
10899 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010900 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010901 mWindow->consumeDragEvent(false, 50, 50);
10902 mSecondWindow->assertNoEvents();
10903
10904 // Move to another window.
10905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010906 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010907 ADISPLAY_ID_DEFAULT, {150, 50}))
10908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010909 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010910 mWindow->consumeDragEvent(true, 150, 50);
10911 mSecondWindow->consumeDragEvent(false, 50, 50);
10912
10913 // drop to another window.
10914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010915 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010916 {150, 50}))
10917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010918 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010919 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010920 mWindow->assertNoEvents();
10921 mSecondWindow->assertNoEvents();
10922}
10923
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010924TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10925 startDrag(true, AINPUT_SOURCE_MOUSE);
10926 // Move on window.
10927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010928 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010929 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10930 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010931 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010932 .x(50)
10933 .y(50))
10934 .build()))
10935 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010936 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010937 mWindow->consumeDragEvent(false, 50, 50);
10938 mSecondWindow->assertNoEvents();
10939
10940 // Move to another window.
10941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010942 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010943 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10944 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010945 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010946 .x(150)
10947 .y(50))
10948 .build()))
10949 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010950 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010951 mWindow->consumeDragEvent(true, 150, 50);
10952 mSecondWindow->consumeDragEvent(false, 50, 50);
10953
10954 // drop to another window.
10955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010956 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010957 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10958 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010959 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010960 .x(150)
10961 .y(50))
10962 .build()))
10963 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010964 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010965 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010966 mWindow->assertNoEvents();
10967 mSecondWindow->assertNoEvents();
10968}
10969
Linnan Li5af92f92023-07-14 14:36:22 +080010970/**
10971 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10972 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10973 */
10974TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10975 // Down on second window
10976 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10977 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10978 {150, 50}))
10979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10980
10981 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10982 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10983
10984 // Down on first window
10985 const MotionEvent secondFingerDownEvent =
10986 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10987 .displayId(ADISPLAY_ID_DEFAULT)
10988 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10989 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10990 .build();
10991 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10992 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10993 InputEventInjectionSync::WAIT_FOR_RESULT))
10994 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10995 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10996 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10997 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10998
10999 // Start drag on first window
11000 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
11001
11002 // Trigger cancel
11003 mDispatcher->cancelCurrentTouch();
11004 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000011005 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
11006 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080011007 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
11008
11009 ASSERT_TRUE(mDispatcher->waitForIdle());
11010 // The D&D finished with nullptr
11011 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
11012
11013 // Remove drag window
11014 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11015
11016 // Inject a simple gesture, ensure dispatcher not crashed
11017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11018 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11019 PointF{50, 50}))
11020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11021 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
11022
11023 const MotionEvent moveEvent =
11024 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11025 .displayId(ADISPLAY_ID_DEFAULT)
11026 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11027 .build();
11028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11029 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
11030 InputEventInjectionSync::WAIT_FOR_RESULT))
11031 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11032 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
11033
11034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11035 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
11036 {50, 50}))
11037 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11038 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
11039}
11040
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011041TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
11042 // Start hovering over the window.
11043 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11044 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
11045 ADISPLAY_ID_DEFAULT, {50, 50}));
11046
11047 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11048 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
11049
11050 ASSERT_FALSE(startDrag(/*sendDown=*/false))
11051 << "Drag and drop should not work with a hovering pointer";
11052}
11053
Vishnu Nair062a8672021-09-03 16:07:44 -070011054class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
11055
11056TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
11057 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011058 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11059 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011060 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011061 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11062 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011063 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011064 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011065 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011066
11067 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011068 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011069 window->assertNoEvents();
11070
Prabir Pradhan678438e2023-04-13 19:32:51 +000011071 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11072 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11074 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080011075 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070011076 window->assertNoEvents();
11077
11078 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011079 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011080 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011081
Prabir Pradhan678438e2023-04-13 19:32:51 +000011082 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011083 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11084
Prabir Pradhan678438e2023-04-13 19:32:51 +000011085 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11086 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011087 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11088 window->assertNoEvents();
11089}
11090
11091TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
11092 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11093 std::make_shared<FakeApplicationHandle>();
11094 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011095 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11096 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011097 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011098 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011099 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011101 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11102 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011103 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011104 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011105 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11106 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011107 mDispatcher->onWindowInfosChanged(
11108 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011109 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011110 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011111
11112 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011113 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011114 window->assertNoEvents();
11115
Prabir Pradhan678438e2023-04-13 19:32:51 +000011116 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11117 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011118 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11119 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011120 window->assertNoEvents();
11121
11122 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011123 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011124 mDispatcher->onWindowInfosChanged(
11125 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011126
Prabir Pradhan678438e2023-04-13 19:32:51 +000011127 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011128 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11129
Prabir Pradhan678438e2023-04-13 19:32:51 +000011130 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11131 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011132 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
11133 window->assertNoEvents();
11134}
11135
11136TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
11137 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
11138 std::make_shared<FakeApplicationHandle>();
11139 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011140 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
11141 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011142 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011143 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011144 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011146 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11147 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011148 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011149 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011150 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11151 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011152 mDispatcher->onWindowInfosChanged(
11153 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011154 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011155 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011156
11157 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011158 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011159 window->assertNoEvents();
11160
Prabir Pradhan678438e2023-04-13 19:32:51 +000011161 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11162 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011163 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11164 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011165 window->assertNoEvents();
11166
11167 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011168 mDispatcher->onWindowInfosChanged(
11169 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011170
Prabir Pradhan678438e2023-04-13 19:32:51 +000011171 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011172 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11173
Prabir Pradhan678438e2023-04-13 19:32:51 +000011174 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11175 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011176 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11177 window->assertNoEvents();
11178}
11179
Antonio Kantekf16f2832021-09-28 04:39:20 +000011180class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11181protected:
11182 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011183 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011184 sp<FakeWindowHandle> mWindow;
11185 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011186 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011187
11188 void SetUp() override {
11189 InputDispatcherTest::SetUp();
11190
11191 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011192 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011193 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011194 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011195 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011196 mSecondWindow =
11197 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011198 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011199 mThirdWindow =
11200 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11201 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11202 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011203
11204 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011205 mDispatcher->onWindowInfosChanged(
11206 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11207 {},
11208 0,
11209 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011210 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011211 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011212
Antonio Kantek15beb512022-06-13 22:35:41 +000011213 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011214 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011215 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011216 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11217 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011218 mThirdWindow->assertNoEvents();
11219 }
11220
11221 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11222 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011223 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011224 SECOND_DISPLAY_ID)) {
11225 mWindow->assertNoEvents();
11226 mSecondWindow->assertNoEvents();
11227 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011228 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011229 }
11230
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011231 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011232 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011233 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11234 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011235 mWindow->consumeTouchModeEvent(inTouchMode);
11236 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011237 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011238 }
11239};
11240
Antonio Kantek26defcf2022-02-08 01:12:27 +000011241TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011242 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011243 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11244 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011245 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011246}
11247
Antonio Kantek26defcf2022-02-08 01:12:27 +000011248TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11249 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011250 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011251 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011252 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011253 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011254 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011255 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011256 mWindow->assertNoEvents();
11257 mSecondWindow->assertNoEvents();
11258}
11259
11260TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11261 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011262 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011263 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011264 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011265 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011266 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011267}
11268
Antonio Kantekf16f2832021-09-28 04:39:20 +000011269TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011270 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011271 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11272 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011273 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011274 mWindow->assertNoEvents();
11275 mSecondWindow->assertNoEvents();
11276}
11277
Antonio Kantek15beb512022-06-13 22:35:41 +000011278TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11279 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11280 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11281 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011282 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011283 mWindow->assertNoEvents();
11284 mSecondWindow->assertNoEvents();
11285 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11286}
11287
Antonio Kantek48710e42022-03-24 14:19:30 -070011288TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11289 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11291 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011292 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11293 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11294
11295 // Then remove focus.
11296 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011297 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011298
11299 // Assert that caller can switch touch mode by owning one of the last interacted window.
11300 const WindowInfo& windowInfo = *mWindow->getInfo();
11301 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11302 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011303 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011304}
11305
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011306class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11307public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011308 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011309 std::shared_ptr<FakeApplicationHandle> application =
11310 std::make_shared<FakeApplicationHandle>();
11311 std::string name = "Fake Spy ";
11312 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011313 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11314 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011315 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011316 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011317 return spy;
11318 }
11319
11320 sp<FakeWindowHandle> createForeground() {
11321 std::shared_ptr<FakeApplicationHandle> application =
11322 std::make_shared<FakeApplicationHandle>();
11323 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011324 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11325 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011326 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011327 return window;
11328 }
11329
11330private:
11331 int mSpyCount{0};
11332};
11333
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011334using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011335/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011336 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11337 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011338TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011339 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011340 ScopedSilentDeath _silentDeath;
11341
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011342 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011343 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011344 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011345 ".* not a trusted overlay");
11346}
11347
11348/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011349 * Input injection into a display with a spy window but no foreground windows should succeed.
11350 */
11351TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011352 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011353 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011354
11355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011356 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11358 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11359}
11360
11361/**
11362 * Verify the order in which different input windows receive events. The touched foreground window
11363 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11364 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11365 * receive events before ones belows it.
11366 *
11367 * Here, we set up a scenario with four windows in the following Z order from the top:
11368 * spy1, spy2, window, spy3.
11369 * We then inject an event and verify that the foreground "window" receives it first, followed by
11370 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11371 * window.
11372 */
11373TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11374 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011375 auto spy1 = createSpy();
11376 auto spy2 = createSpy();
11377 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011378 mDispatcher->onWindowInfosChanged(
11379 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011380 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11381 const size_t numChannels = channels.size();
11382
Michael Wright8e9a8562022-02-09 13:44:29 +000011383 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011384 if (!epollFd.ok()) {
11385 FAIL() << "Failed to create epoll fd";
11386 }
11387
11388 for (size_t i = 0; i < numChannels; i++) {
11389 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11390 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11391 FAIL() << "Failed to add fd to epoll";
11392 }
11393 }
11394
11395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011396 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11398
11399 std::vector<size_t> eventOrder;
11400 std::vector<struct epoll_event> events(numChannels);
11401 for (;;) {
11402 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11403 (100ms).count());
11404 if (nFds < 0) {
11405 FAIL() << "Failed to call epoll_wait";
11406 }
11407 if (nFds == 0) {
11408 break; // epoll_wait timed out
11409 }
11410 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011411 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011412 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011413 channels[i]->consumeMotionDown();
11414 }
11415 }
11416
11417 // Verify the order in which the events were received.
11418 EXPECT_EQ(3u, eventOrder.size());
11419 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11420 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11421 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11422}
11423
11424/**
11425 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11426 */
11427TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11428 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011429 auto spy = createSpy();
11430 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011431 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011432
11433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011434 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11436 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11437 spy->assertNoEvents();
11438}
11439
11440/**
11441 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11442 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11443 * to the window.
11444 */
11445TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11446 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011447 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011448 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011449 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011450
11451 // Inject an event outside the spy window's touchable region.
11452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011453 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11455 window->consumeMotionDown();
11456 spy->assertNoEvents();
11457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011458 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11460 window->consumeMotionUp();
11461 spy->assertNoEvents();
11462
11463 // Inject an event inside the spy window's touchable region.
11464 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011465 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011466 {5, 10}))
11467 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11468 window->consumeMotionDown();
11469 spy->consumeMotionDown();
11470}
11471
11472/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011473 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011474 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011475 */
11476TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11477 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011478 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011479 auto spy = createSpy();
11480 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011481 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011482 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011483 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011484
11485 // Inject an event outside the spy window's frame and touchable region.
11486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011487 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011488 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011489 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11490 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011491 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011492}
11493
11494/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011495 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11496 * pointers that are down within its bounds.
11497 */
11498TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11499 auto windowLeft = createForeground();
11500 windowLeft->setFrame({0, 0, 100, 200});
11501 auto windowRight = createForeground();
11502 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011503 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011504 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011505 mDispatcher->onWindowInfosChanged(
11506 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011507
11508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011509 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011510 {50, 50}))
11511 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11512 windowLeft->consumeMotionDown();
11513 spy->consumeMotionDown();
11514
11515 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011516 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011517 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011518 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11519 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011520 .build();
11521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011522 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011523 InputEventInjectionSync::WAIT_FOR_RESULT))
11524 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11525 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011526 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011527}
11528
11529/**
11530 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11531 * the spy should receive the second pointer with ACTION_DOWN.
11532 */
11533TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11534 auto window = createForeground();
11535 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011536 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011537 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011538 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011539
11540 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011541 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011542 {50, 50}))
11543 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11544 window->consumeMotionDown();
11545 spyRight->assertNoEvents();
11546
11547 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011548 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011549 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011550 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11551 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011552 .build();
11553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011554 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011555 InputEventInjectionSync::WAIT_FOR_RESULT))
11556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011557 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011558 spyRight->consumeMotionDown();
11559}
11560
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011561/**
11562 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11563 * windows should be allowed to control split touch.
11564 */
11565TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011566 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011567 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011568 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011569 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011570
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011571 auto window = createForeground();
11572 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011573
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011574 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011575
11576 // First finger down, no window touched.
11577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011578 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011579 {100, 200}))
11580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11581 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11582 window->assertNoEvents();
11583
11584 // Second finger down on window, the window should receive touch down.
11585 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011586 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011587 .displayId(ADISPLAY_ID_DEFAULT)
11588 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011589 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11590 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011591 .build();
11592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011593 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011594 InputEventInjectionSync::WAIT_FOR_RESULT))
11595 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11596
11597 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011598 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011599}
11600
11601/**
11602 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11603 * do not receive key events.
11604 */
11605TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011606 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011607 spy->setFocusable(false);
11608
11609 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011610 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011611 setFocusedWindow(window);
11612 window->consumeFocusEvent(true);
11613
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011615 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11616 window->consumeKeyDown(ADISPLAY_ID_NONE);
11617
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011619 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11620 window->consumeKeyUp(ADISPLAY_ID_NONE);
11621
11622 spy->assertNoEvents();
11623}
11624
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011625using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11626
11627/**
11628 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11629 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11630 */
11631TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11632 auto window = createForeground();
11633 auto spy1 = createSpy();
11634 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011635 mDispatcher->onWindowInfosChanged(
11636 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011637
11638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011639 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011640 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11641 window->consumeMotionDown();
11642 spy1->consumeMotionDown();
11643 spy2->consumeMotionDown();
11644
11645 // Pilfer pointers from the second spy window.
11646 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11647 spy2->assertNoEvents();
11648 spy1->consumeMotionCancel();
11649 window->consumeMotionCancel();
11650
11651 // The rest of the gesture should only be sent to the second spy window.
11652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011653 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011654 ADISPLAY_ID_DEFAULT))
11655 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11656 spy2->consumeMotionMove();
11657 spy1->assertNoEvents();
11658 window->assertNoEvents();
11659}
11660
11661/**
11662 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11663 * in the middle of the gesture.
11664 */
11665TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11666 auto window = createForeground();
11667 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011668 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011669
11670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011671 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11673 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11674 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11675
11676 window->releaseChannel();
11677
11678 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11679
11680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011681 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011682 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11683 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11684}
11685
11686/**
11687 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11688 * the spy, but not to any other windows.
11689 */
11690TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11691 auto spy = createSpy();
11692 auto window = createForeground();
11693
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011694 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011695
11696 // First finger down on the window and the spy.
11697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011698 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011699 {100, 200}))
11700 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11701 spy->consumeMotionDown();
11702 window->consumeMotionDown();
11703
11704 // Spy window pilfers the pointers.
11705 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11706 window->consumeMotionCancel();
11707
11708 // Second finger down on the window and spy, but the window should not receive the pointer down.
11709 const MotionEvent secondFingerDownEvent =
11710 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11711 .displayId(ADISPLAY_ID_DEFAULT)
11712 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011713 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11714 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011715 .build();
11716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011717 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011718 InputEventInjectionSync::WAIT_FOR_RESULT))
11719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11720
Harry Cutts33476232023-01-30 19:57:29 +000011721 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011722
11723 // Third finger goes down outside all windows, so injection should fail.
11724 const MotionEvent thirdFingerDownEvent =
11725 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11726 .displayId(ADISPLAY_ID_DEFAULT)
11727 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011728 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11729 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11730 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011731 .build();
11732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011733 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011734 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011735 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011736
11737 spy->assertNoEvents();
11738 window->assertNoEvents();
11739}
11740
11741/**
11742 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11743 */
11744TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11745 auto spy = createSpy();
11746 spy->setFrame(Rect(0, 0, 100, 100));
11747 auto window = createForeground();
11748 window->setFrame(Rect(0, 0, 200, 200));
11749
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011750 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011751
11752 // First finger down on the window only
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 {150, 150}))
11756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11757 window->consumeMotionDown();
11758
11759 // Second finger down on the spy and window
11760 const MotionEvent secondFingerDownEvent =
11761 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11762 .displayId(ADISPLAY_ID_DEFAULT)
11763 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011764 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11765 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011766 .build();
11767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011768 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011769 InputEventInjectionSync::WAIT_FOR_RESULT))
11770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11771 spy->consumeMotionDown();
11772 window->consumeMotionPointerDown(1);
11773
11774 // Third finger down on the spy and window
11775 const MotionEvent thirdFingerDownEvent =
11776 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11777 .displayId(ADISPLAY_ID_DEFAULT)
11778 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011779 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11780 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11781 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011782 .build();
11783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011784 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011785 InputEventInjectionSync::WAIT_FOR_RESULT))
11786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11787 spy->consumeMotionPointerDown(1);
11788 window->consumeMotionPointerDown(2);
11789
11790 // Spy window pilfers the pointers.
11791 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011792 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11793 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011794
11795 spy->assertNoEvents();
11796 window->assertNoEvents();
11797}
11798
11799/**
11800 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11801 * other windows should be canceled. If this results in the cancellation of all pointers for some
11802 * window, then that window should receive ACTION_CANCEL.
11803 */
11804TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11805 auto spy = createSpy();
11806 spy->setFrame(Rect(0, 0, 100, 100));
11807 auto window = createForeground();
11808 window->setFrame(Rect(0, 0, 200, 200));
11809
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011810 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011811
11812 // First finger down on both spy and window
11813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011815 {10, 10}))
11816 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11817 window->consumeMotionDown();
11818 spy->consumeMotionDown();
11819
11820 // Second finger down on the spy and window
11821 const MotionEvent secondFingerDownEvent =
11822 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11823 .displayId(ADISPLAY_ID_DEFAULT)
11824 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011825 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11826 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011827 .build();
11828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011829 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011830 InputEventInjectionSync::WAIT_FOR_RESULT))
11831 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11832 spy->consumeMotionPointerDown(1);
11833 window->consumeMotionPointerDown(1);
11834
11835 // Spy window pilfers the pointers.
11836 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11837 window->consumeMotionCancel();
11838
11839 spy->assertNoEvents();
11840 window->assertNoEvents();
11841}
11842
11843/**
11844 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11845 * be sent to other windows
11846 */
11847TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11848 auto spy = createSpy();
11849 spy->setFrame(Rect(0, 0, 100, 100));
11850 auto window = createForeground();
11851 window->setFrame(Rect(0, 0, 200, 200));
11852
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011853 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011854
11855 // First finger down on both window and spy
11856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011857 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011858 {10, 10}))
11859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11860 window->consumeMotionDown();
11861 spy->consumeMotionDown();
11862
11863 // Spy window pilfers the pointers.
11864 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11865 window->consumeMotionCancel();
11866
11867 // Second finger down on the window only
11868 const MotionEvent secondFingerDownEvent =
11869 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11870 .displayId(ADISPLAY_ID_DEFAULT)
11871 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011872 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11873 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011874 .build();
11875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011876 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011877 InputEventInjectionSync::WAIT_FOR_RESULT))
11878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11879 window->consumeMotionDown();
11880 window->assertNoEvents();
11881
11882 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11883 spy->consumeMotionMove();
11884 spy->assertNoEvents();
11885}
11886
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011887/**
11888 * A window on the left and a window on the right. Also, a spy window that's above all of the
11889 * windows, and spanning both left and right windows.
11890 * Send simultaneous motion streams from two different devices, one to the left window, and another
11891 * to the right window.
11892 * Pilfer from spy window.
11893 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11894 */
11895TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11896 sp<FakeWindowHandle> spy = createSpy();
11897 spy->setFrame(Rect(0, 0, 200, 200));
11898 sp<FakeWindowHandle> leftWindow = createForeground();
11899 leftWindow->setFrame(Rect(0, 0, 100, 100));
11900
11901 sp<FakeWindowHandle> rightWindow = createForeground();
11902 rightWindow->setFrame(Rect(100, 0, 200, 100));
11903
11904 constexpr int32_t stylusDeviceId = 1;
11905 constexpr int32_t touchDeviceId = 2;
11906
11907 mDispatcher->onWindowInfosChanged(
11908 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11909
11910 // Stylus down on left window and spy
11911 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11912 .deviceId(stylusDeviceId)
11913 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11914 .build());
11915 leftWindow->consumeMotionEvent(
11916 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11917 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11918
11919 // Finger down on right window and spy - but spy already has stylus
11920 mDispatcher->notifyMotion(
11921 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11922 .deviceId(touchDeviceId)
11923 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11924 .build());
11925 rightWindow->consumeMotionEvent(
11926 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011927 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011928
11929 // Act: pilfer from spy. Spy is currently receiving touch events.
11930 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011931 leftWindow->consumeMotionEvent(
11932 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011933 rightWindow->consumeMotionEvent(
11934 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11935
11936 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11937 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11938 .deviceId(stylusDeviceId)
11939 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11940 .build());
11941 mDispatcher->notifyMotion(
11942 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11943 .deviceId(touchDeviceId)
11944 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11945 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011946 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011947
11948 spy->assertNoEvents();
11949 leftWindow->assertNoEvents();
11950 rightWindow->assertNoEvents();
11951}
11952
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011953TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11954 auto window = createForeground();
11955 auto spy = createSpy();
11956 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11957
11958 mDispatcher->notifyMotion(
11959 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11960 .deviceId(1)
11961 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11962 .build());
11963 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11964 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11965
11966 // Pilfer pointers from the spy window should fail.
11967 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11968 spy->assertNoEvents();
11969 window->assertNoEvents();
11970}
11971
Prabir Pradhand65552b2021-10-07 11:23:50 -070011972class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11973public:
11974 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11975 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11976 std::make_shared<FakeApplicationHandle>();
11977 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011978 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11979 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011980 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011981 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011982 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011983 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011984 overlay->setTrustedOverlay(true);
11985
11986 std::shared_ptr<FakeApplicationHandle> application =
11987 std::make_shared<FakeApplicationHandle>();
11988 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011989 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11990 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011991 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011992 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011993
11994 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011995 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011996 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011997 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011998 return {std::move(overlay), std::move(window)};
11999 }
12000
12001 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000012002 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070012003 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000012004 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070012005 }
12006
12007 void sendStylusEvent(int32_t action) {
12008 NotifyMotionArgs motionArgs =
12009 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
12010 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012011 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000012012 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070012013 }
12014};
12015
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012016using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
12017
12018TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070012019 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012020 ScopedSilentDeath _silentDeath;
12021
Prabir Pradhand65552b2021-10-07 11:23:50 -070012022 auto [overlay, window] = setupStylusOverlayScenario();
12023 overlay->setTrustedOverlay(false);
12024 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012025 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
12026 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070012027 ".* not a trusted overlay");
12028}
12029
12030TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
12031 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012032 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012033
12034 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12035 overlay->consumeMotionDown();
12036 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12037 overlay->consumeMotionUp();
12038
12039 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12040 window->consumeMotionDown();
12041 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12042 window->consumeMotionUp();
12043
12044 overlay->assertNoEvents();
12045 window->assertNoEvents();
12046}
12047
12048TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
12049 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012050 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012051 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070012052
12053 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12054 overlay->consumeMotionDown();
12055 window->consumeMotionDown();
12056 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12057 overlay->consumeMotionUp();
12058 window->consumeMotionUp();
12059
12060 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
12061 window->consumeMotionDown();
12062 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
12063 window->consumeMotionUp();
12064
12065 overlay->assertNoEvents();
12066 window->assertNoEvents();
12067}
12068
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012069/**
12070 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
12071 * The scenario is as follows:
12072 * - The stylus interceptor overlay is configured as a spy window.
12073 * - The stylus interceptor spy receives the start of a new stylus gesture.
12074 * - It pilfers pointers and then configures itself to no longer be a spy.
12075 * - The stylus interceptor continues to receive the rest of the gesture.
12076 */
12077TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
12078 auto [overlay, window] = setupStylusOverlayScenario();
12079 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012080 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012081
12082 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
12083 overlay->consumeMotionDown();
12084 window->consumeMotionDown();
12085
12086 // The interceptor pilfers the pointers.
12087 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
12088 window->consumeMotionCancel();
12089
12090 // The interceptor configures itself so that it is no longer a spy.
12091 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012092 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000012093
12094 // It continues to receive the rest of the stylus gesture.
12095 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
12096 overlay->consumeMotionMove();
12097 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
12098 overlay->consumeMotionUp();
12099
12100 window->assertNoEvents();
12101}
12102
Prabir Pradhan5735a322022-04-11 17:23:34 +000012103struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012104 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012105 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000012106 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
12107 std::unique_ptr<InputDispatcher>& mDispatcher;
12108
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012109 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000012110 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
12111
12112 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012113 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012114 ADISPLAY_ID_DEFAULT, {100, 200},
12115 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
12116 AMOTION_EVENT_INVALID_CURSOR_POSITION},
12117 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
12118 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
12119 }
12120
12121 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012122 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012123 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000012124 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000012125 mPolicyFlags);
12126 }
12127
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012128 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000012129 std::shared_ptr<FakeApplicationHandle> overlayApplication =
12130 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012131 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
12132 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000012133 window->setOwnerInfo(mPid, mUid);
12134 return window;
12135 }
12136};
12137
12138using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
12139
12140TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012141 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012142 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012143 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012144
12145 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12146 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12147 window->consumeMotionDown();
12148
12149 setFocusedWindow(window);
12150 window->consumeFocusEvent(true);
12151
12152 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12153 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12154 window->consumeKeyDown(ADISPLAY_ID_NONE);
12155}
12156
12157TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012158 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012159 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012160 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012161
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012162 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012163 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12164 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12165
12166 setFocusedWindow(window);
12167 window->consumeFocusEvent(true);
12168
12169 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12170 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12171 window->assertNoEvents();
12172}
12173
12174TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012175 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012176 auto window = owner.createWindow("Owned window");
12177 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012178 spy->setSpy(true);
12179 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012180 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012181
12182 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12183 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12184 spy->consumeMotionDown();
12185 window->consumeMotionDown();
12186}
12187
12188TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012189 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012190 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012191
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012192 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012193 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012194 randosSpy->setSpy(true);
12195 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012196 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012197
12198 // The event is targeted at owner's window, so injection should succeed, but the spy should
12199 // not receive the event.
12200 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12201 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12202 randosSpy->assertNoEvents();
12203 window->consumeMotionDown();
12204}
12205
12206TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012207 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012208 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012209
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012210 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012211 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012212 randosSpy->setSpy(true);
12213 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012214 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012215
12216 // A user that has injection permission can inject into any window.
12217 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012218 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012219 ADISPLAY_ID_DEFAULT));
12220 randosSpy->consumeMotionDown();
12221 window->consumeMotionDown();
12222
12223 setFocusedWindow(randosSpy);
12224 randosSpy->consumeFocusEvent(true);
12225
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012226 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012227 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12228 window->assertNoEvents();
12229}
12230
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012231TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012232 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012233 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012234
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012235 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012236 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012237 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12238 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012239 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012240
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012241 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012242 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12243 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12244 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012245 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012246}
12247
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012248using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12249
12250TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12251 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12252
12253 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12254 ADISPLAY_ID_DEFAULT);
12255 left->setFrame(Rect(0, 0, 100, 100));
12256 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12257 "Right Window", ADISPLAY_ID_DEFAULT);
12258 right->setFrame(Rect(100, 0, 200, 100));
12259 sp<FakeWindowHandle> spy =
12260 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12261 spy->setFrame(Rect(0, 0, 200, 100));
12262 spy->setTrustedOverlay(true);
12263 spy->setSpy(true);
12264
12265 mDispatcher->onWindowInfosChanged(
12266 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12267
12268 // Hover into the left window.
12269 mDispatcher->notifyMotion(
12270 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12271 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12272 .build());
12273
12274 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12275 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12276
12277 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12278 /*pointerId=*/0));
12279 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12280 /*pointerId=*/0));
12281 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12282 /*pointerId=*/0));
12283
12284 // Hover move to the right window.
12285 mDispatcher->notifyMotion(
12286 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12287 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12288 .build());
12289
12290 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12291 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12292 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12293
12294 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12295 /*pointerId=*/0));
12296 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12297 /*pointerId=*/0));
12298 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12299 /*pointerId=*/0));
12300
12301 // Stop hovering.
12302 mDispatcher->notifyMotion(
12303 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12304 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12305 .build());
12306
12307 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12308 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12309
12310 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12311 /*pointerId=*/0));
12312 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12313 /*pointerId=*/0));
12314 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12315 /*pointerId=*/0));
12316}
12317
12318TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12319 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12320
12321 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12322 ADISPLAY_ID_DEFAULT);
12323 left->setFrame(Rect(0, 0, 100, 100));
12324 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12325 "Right Window", ADISPLAY_ID_DEFAULT);
12326 right->setFrame(Rect(100, 0, 200, 100));
12327 sp<FakeWindowHandle> spy =
12328 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12329 spy->setFrame(Rect(0, 0, 200, 100));
12330 spy->setTrustedOverlay(true);
12331 spy->setSpy(true);
12332
12333 mDispatcher->onWindowInfosChanged(
12334 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12335
12336 // First pointer down on left window.
12337 mDispatcher->notifyMotion(
12338 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12339 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12340 .build());
12341
12342 left->consumeMotionDown();
12343 spy->consumeMotionDown();
12344
12345 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12346 /*pointerId=*/0));
12347 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12348 /*pointerId=*/0));
12349 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12350 /*pointerId=*/0));
12351
12352 // Second pointer down on right window.
12353 mDispatcher->notifyMotion(
12354 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12355 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12356 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12357 .build());
12358
12359 left->consumeMotionMove();
12360 right->consumeMotionDown();
12361 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12362
12363 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12364 /*pointerId=*/0));
12365 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12366 /*pointerId=*/0));
12367 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12368 /*pointerId=*/0));
12369 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12370 /*pointerId=*/1));
12371 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12372 /*pointerId=*/1));
12373 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12374 /*pointerId=*/1));
12375
12376 // Second pointer up.
12377 mDispatcher->notifyMotion(
12378 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12379 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12381 .build());
12382
12383 left->consumeMotionMove();
12384 right->consumeMotionUp();
12385 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12386
12387 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12388 /*pointerId=*/0));
12389 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12390 /*pointerId=*/0));
12391 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12392 /*pointerId=*/0));
12393 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12394 /*pointerId=*/1));
12395 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12396 /*pointerId=*/1));
12397 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12398 /*pointerId=*/1));
12399
12400 // First pointer up.
12401 mDispatcher->notifyMotion(
12402 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12403 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12404 .build());
12405
12406 left->consumeMotionUp();
12407 spy->consumeMotionUp();
12408
12409 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12410 /*pointerId=*/0));
12411 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12412 /*pointerId=*/0));
12413 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12414 /*pointerId=*/0));
12415}
12416
12417TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12419
12420 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12421 ADISPLAY_ID_DEFAULT);
12422 left->setFrame(Rect(0, 0, 100, 100));
12423 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12424 "Right Window", ADISPLAY_ID_DEFAULT);
12425 right->setFrame(Rect(100, 0, 200, 100));
12426
12427 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12428
12429 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12430 /*pointerId=*/0));
12431 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12432 /*pointerId=*/0));
12433
12434 // Hover move into the window.
12435 mDispatcher->notifyMotion(
12436 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12437 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12438 .rawXCursorPosition(50)
12439 .rawYCursorPosition(50)
12440 .deviceId(DEVICE_ID)
12441 .build());
12442
12443 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12444
12445 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12446 /*pointerId=*/0));
12447
12448 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12449 mDispatcher->notifyMotion(
12450 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12451 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12452 .rawXCursorPosition(51)
12453 .rawYCursorPosition(50)
12454 .deviceId(SECOND_DEVICE_ID)
12455 .build());
12456
12457 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12458 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12459
12460 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12461 // a HOVER_EXIT from the first device.
12462 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12463 /*pointerId=*/0));
12464 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12465 SECOND_DEVICE_ID,
12466 /*pointerId=*/0));
12467
12468 // Move the mouse outside the window. Document the current behavior, where the window does not
12469 // receive HOVER_EXIT even though the mouse left the window.
12470 mDispatcher->notifyMotion(
12471 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12472 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12473 .rawXCursorPosition(150)
12474 .rawYCursorPosition(50)
12475 .deviceId(SECOND_DEVICE_ID)
12476 .build());
12477
12478 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12479 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12480 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12481 /*pointerId=*/0));
12482 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12483 SECOND_DEVICE_ID,
12484 /*pointerId=*/0));
12485}
12486
Garfield Tane84e6f92019-08-29 17:28:41 -070012487} // namespace android::inputdispatcher