blob: 01bc2f3a86c11c8c1cdcbdd12fb0d3528a595b32 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000018#include "../BlockingQueue.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070019#include "FakeApplicationHandle.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 Vishniakou870ecec2020-12-09 08:07:46 -100034#include <input/Input.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070035#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080036#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080037#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100038
Garfield Tan1c7bc862020-01-28 13:24:04 -080039#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080040#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070041#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080043#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080044
Garfield Tan1c7bc862020-01-28 13:24:04 -080045using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050046using android::gui::FocusRequest;
47using android::gui::TouchOcclusionMode;
48using android::gui::WindowInfo;
49using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080050using android::os::InputEventInjectionResult;
51using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080052
Garfield Tane84e6f92019-08-29 17:28:41 -070053namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080054
Dominik Laskowski2f01d772022-03-23 16:01:29 -070055using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080056using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000057using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070059namespace {
60
Michael Wrightd02c5b62014-02-10 15:10:22 -080061// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000062static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080063
64// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000065static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080066static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080067
Jeff Brownf086ddb2014-02-11 14:28:48 -080068// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000069static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
70static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080071
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000072// Ensure common actions are interchangeable between keys and motions for convenience.
73static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
74static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080075static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
76static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
77static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
78static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070079static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080080static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070081static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080082static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080083static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080084/**
85 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
86 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
87 * index 0) is the new pointer going down. The same pointer could have been placed at a different
88 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
89 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
90 * pointer id=0 leaves but the pointer id=1 remains.
91 */
92static constexpr int32_t POINTER_0_DOWN =
93 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080094static constexpr int32_t POINTER_1_DOWN =
95 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000096static constexpr int32_t POINTER_2_DOWN =
97 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +000098static constexpr int32_t POINTER_3_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000100static constexpr int32_t POINTER_0_UP =
101 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800102static constexpr int32_t POINTER_1_UP =
103 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000104static constexpr int32_t POINTER_2_UP =
105 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800106
Antonio Kantek15beb512022-06-13 22:35:41 +0000107// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000108static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000109static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000110
Antonio Kantek15beb512022-06-13 22:35:41 +0000111// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000112static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000113static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000114
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000115// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000116static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700118/**
119 * If we expect to receive the event, the timeout can be made very long. When the test are running
120 * correctly, we will actually never wait until the end of the timeout because the wait will end
121 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
122 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
123 * developer can see the failure quickly (on human scale).
124 */
125static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
126/**
127 * When no event is expected, we can have a very short timeout. A large value here would slow down
128 * the tests. In the unlikely event of system being too slow, the event may still be present but the
129 * timeout would complete before it is consumed. This would result in test flakiness. If this
130 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
131 * would get noticed and addressed quickly.
132 */
133static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
134
Arthur Hungc539dbb2022-12-08 07:45:36 +0000135static constexpr int expectedWallpaperFlags =
136 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
137
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800138using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
139
Gang Wang342c9272020-01-13 13:15:04 -0500140/**
141 * Return a DOWN key event with KEYCODE_A.
142 */
143static KeyEvent getTestKeyEvent() {
144 KeyEvent event;
145
Garfield Tanfbe732e2020-01-24 11:26:14 -0800146 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
147 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
148 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500149 return event;
150}
151
Michael Wrightd02c5b62014-02-10 15:10:22 -0800152// --- FakeInputDispatcherPolicy ---
153
154class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000155 struct AnrResult {
156 sp<IBinder> token{};
157 gui::Pid pid{gui::Pid::INVALID};
158 };
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800159 /* Stores data about a user-activity-poke event from the dispatcher. */
160 struct UserActivityPokeEvent {
161 nsecs_t eventTime;
162 int32_t eventType;
163 int32_t displayId;
164
165 bool operator==(const UserActivityPokeEvent& rhs) const = default;
166
167 friend std::ostream& operator<<(std::ostream& os, const UserActivityPokeEvent& ev) {
168 os << "UserActivityPokeEvent[time=" << ev.eventTime << ", eventType=" << ev.eventType
169 << ", displayId=" << ev.displayId << "]";
170 return os;
171 }
172 };
Prabir Pradhanedd96402022-02-15 01:46:16 -0800173
Michael Wrightd02c5b62014-02-10 15:10:22 -0800174public:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000175 FakeInputDispatcherPolicy() = default;
176 virtual ~FakeInputDispatcherPolicy() = default;
Jackal Guof9696682018-10-05 12:23:23 +0800177
Siarhei Vishniakou8935a802019-11-15 16:41:44 -0800178 void assertFilterInputEventWasCalled(const NotifyKeyArgs& args) {
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700179 assertFilterInputEventWasCalledInternal([&args](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700180 ASSERT_EQ(event.getType(), InputEventType::KEY);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700181 EXPECT_EQ(event.getDisplayId(), args.displayId);
182
183 const auto& keyEvent = static_cast<const KeyEvent&>(event);
184 EXPECT_EQ(keyEvent.getEventTime(), args.eventTime);
185 EXPECT_EQ(keyEvent.getAction(), args.action);
186 });
Jackal Guof9696682018-10-05 12:23:23 +0800187 }
188
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700189 void assertFilterInputEventWasCalled(const NotifyMotionArgs& args, vec2 point) {
190 assertFilterInputEventWasCalledInternal([&](const InputEvent& event) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700191 ASSERT_EQ(event.getType(), InputEventType::MOTION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700192 EXPECT_EQ(event.getDisplayId(), args.displayId);
193
194 const auto& motionEvent = static_cast<const MotionEvent&>(event);
195 EXPECT_EQ(motionEvent.getEventTime(), args.eventTime);
196 EXPECT_EQ(motionEvent.getAction(), args.action);
Prabir Pradhan00e029d2023-03-09 20:11:09 +0000197 EXPECT_NEAR(motionEvent.getX(0), point.x, MotionEvent::ROUNDING_PRECISION);
198 EXPECT_NEAR(motionEvent.getY(0), point.y, MotionEvent::ROUNDING_PRECISION);
199 EXPECT_NEAR(motionEvent.getRawX(0), point.x, MotionEvent::ROUNDING_PRECISION);
200 EXPECT_NEAR(motionEvent.getRawY(0), point.y, MotionEvent::ROUNDING_PRECISION);
Prabir Pradhan81420cc2021-09-06 10:28:50 -0700201 });
Jackal Guof9696682018-10-05 12:23:23 +0800202 }
203
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700204 void assertFilterInputEventWasNotCalled() {
205 std::scoped_lock lock(mLock);
206 ASSERT_EQ(nullptr, mFilteredEvent);
207 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800208
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800209 void assertNotifyConfigurationChangedWasCalled(nsecs_t when) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700210 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800211 ASSERT_TRUE(mConfigurationChangedTime)
212 << "Timed out waiting for configuration changed call";
213 ASSERT_EQ(*mConfigurationChangedTime, when);
214 mConfigurationChangedTime = std::nullopt;
215 }
216
217 void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700218 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800219 ASSERT_TRUE(mLastNotifySwitch);
Garfield Tanc51d1ba2020-01-28 13:24:04 -0800220 // We do not check id because it is not exposed to the policy
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800221 EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
222 EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
223 EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
224 EXPECT_EQ(args.switchMask, mLastNotifySwitch->switchMask);
225 mLastNotifySwitch = std::nullopt;
226 }
227
chaviwfd6d3512019-03-25 13:23:49 -0700228 void assertOnPointerDownEquals(const sp<IBinder>& touchedToken) {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700229 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800230 ASSERT_EQ(touchedToken, mOnPointerDownToken);
231 mOnPointerDownToken.clear();
232 }
233
234 void assertOnPointerDownWasNotCalled() {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700235 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800236 ASSERT_TRUE(mOnPointerDownToken == nullptr)
237 << "Expected onPointerDownOutsideFocus to not have been called";
chaviwfd6d3512019-03-25 13:23:49 -0700238 }
239
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700240 // This function must be called soon after the expected ANR timer starts,
241 // because we are also checking how much time has passed.
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500242 void assertNotifyNoFocusedWindowAnrWasCalled(
Chris Yea209fde2020-07-22 13:54:51 -0700243 std::chrono::nanoseconds timeout,
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500244 const std::shared_ptr<InputApplicationHandle>& expectedApplication) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800245 std::unique_lock lock(mLock);
246 android::base::ScopedLockAssertion assumeLocked(mLock);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500247 std::shared_ptr<InputApplicationHandle> application;
Prabir Pradhanedd96402022-02-15 01:46:16 -0800248 ASSERT_NO_FATAL_FAILURE(
249 application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500250 ASSERT_EQ(expectedApplication, application);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700251 }
252
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000253 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800254 const sp<WindowInfoHandle>& window) {
255 LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null");
256 assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(),
257 window->getInfo()->ownerPid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500258 }
259
Prabir Pradhanedd96402022-02-15 01:46:16 -0800260 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
261 const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000262 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800263 std::unique_lock lock(mLock);
264 android::base::ScopedLockAssertion assumeLocked(mLock);
265 AnrResult result;
266 ASSERT_NO_FATAL_FAILURE(result =
267 getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000268 ASSERT_EQ(expectedToken, result.token);
269 ASSERT_EQ(expectedPid, result.pid);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500270 }
271
Prabir Pradhanedd96402022-02-15 01:46:16 -0800272 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000273 sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500274 std::unique_lock lock(mLock);
275 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800276 AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock);
277 const auto& [token, _] = result;
278 return token;
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000279 }
280
Prabir Pradhanedd96402022-02-15 01:46:16 -0800281 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000282 gui::Pid expectedPid) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800283 std::unique_lock lock(mLock);
284 android::base::ScopedLockAssertion assumeLocked(mLock);
285 AnrResult result;
286 ASSERT_NO_FATAL_FAILURE(
287 result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000288 ASSERT_EQ(expectedToken, result.token);
289 ASSERT_EQ(expectedPid, result.pid);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800290 }
291
292 /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */
Siarhei Vishniakou3c63fa42020-12-15 02:59:54 +0000293 sp<IBinder> getResponsiveWindowToken() {
294 std::unique_lock lock(mLock);
295 android::base::ScopedLockAssertion assumeLocked(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800296 AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock);
297 const auto& [token, _] = result;
298 return token;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700299 }
300
301 void assertNotifyAnrWasNotCalled() {
302 std::scoped_lock lock(mLock);
303 ASSERT_TRUE(mAnrApplications.empty());
Prabir Pradhanedd96402022-02-15 01:46:16 -0800304 ASSERT_TRUE(mAnrWindows.empty());
305 ASSERT_TRUE(mResponsiveWindows.empty())
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500306 << "ANR was not called, but please also consume the 'connection is responsive' "
307 "signal";
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700308 }
309
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000310 PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800311 std::unique_lock lock(mLock);
312 base::ScopedLockAssertion assumeLocked(mLock);
313
314 if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
315 [this, enabled]() REQUIRES(mLock) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000316 return mPointerCaptureRequest->enable ==
Prabir Pradhan99987712020-11-10 18:43:05 -0800317 enabled;
318 })) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000319 ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
320 << ") to be called.";
321 return {};
Prabir Pradhan99987712020-11-10 18:43:05 -0800322 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000323 auto request = *mPointerCaptureRequest;
324 mPointerCaptureRequest.reset();
325 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -0800326 }
327
328 void assertSetPointerCaptureNotCalled() {
329 std::unique_lock lock(mLock);
330 base::ScopedLockAssertion assumeLocked(mLock);
331
332 if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000333 FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
Prabir Pradhan99987712020-11-10 18:43:05 -0800334 "enabled = "
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000335 << std::to_string(mPointerCaptureRequest->enable);
Prabir Pradhan99987712020-11-10 18:43:05 -0800336 }
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000337 mPointerCaptureRequest.reset();
Prabir Pradhan99987712020-11-10 18:43:05 -0800338 }
339
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -0700340 void assertDropTargetEquals(const InputDispatcherInterface& dispatcher,
341 const sp<IBinder>& targetToken) {
342 dispatcher.waitForIdle();
arthurhungf452d0b2021-01-06 00:19:52 +0800343 std::scoped_lock lock(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800344 ASSERT_TRUE(mNotifyDropWindowWasCalled);
arthurhungf452d0b2021-01-06 00:19:52 +0800345 ASSERT_EQ(targetToken, mDropTargetWindowToken);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800346 mNotifyDropWindowWasCalled = false;
arthurhungf452d0b2021-01-06 00:19:52 +0800347 }
348
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800349 void assertNotifyInputChannelBrokenWasCalled(const sp<IBinder>& token) {
350 std::unique_lock lock(mLock);
351 base::ScopedLockAssertion assumeLocked(mLock);
352 std::optional<sp<IBinder>> receivedToken =
353 getItemFromStorageLockedInterruptible(100ms, mBrokenInputChannels, lock,
354 mNotifyInputChannelBroken);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000355 ASSERT_TRUE(receivedToken.has_value()) << "Did not receive the broken channel token";
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800356 ASSERT_EQ(token, *receivedToken);
357 }
358
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800359 /**
360 * Set policy timeout. A value of zero means next key will not be intercepted.
361 */
362 void setInterceptKeyTimeout(std::chrono::milliseconds timeout) {
363 mInterceptKeyTimeout = timeout;
364 }
365
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800366 std::chrono::nanoseconds getKeyWaitingForEventsTimeout() override { return 500ms; }
367
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700368 void setStaleEventTimeout(std::chrono::nanoseconds timeout) { mStaleEventTimeout = timeout; }
369
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800370 void assertUserActivityNotPoked() {
371 std::unique_lock lock(mLock);
372 base::ScopedLockAssertion assumeLocked(mLock);
373
374 std::optional<UserActivityPokeEvent> pokeEvent =
375 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
376 mNotifyUserActivity);
377
378 ASSERT_FALSE(pokeEvent) << "Expected user activity not to have been poked";
Josep del Riob3981622023-04-18 15:49:45 +0000379 }
380
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800381 /**
382 * Asserts that a user activity poke has happened. The earliest recorded poke event will be
383 * cleared after this call.
384 *
385 * If an expected UserActivityPokeEvent is provided, asserts that the given event is the
386 * earliest recorded poke event.
387 */
388 void assertUserActivityPoked(std::optional<UserActivityPokeEvent> expectedPokeEvent = {}) {
389 std::unique_lock lock(mLock);
390 base::ScopedLockAssertion assumeLocked(mLock);
391
392 std::optional<UserActivityPokeEvent> pokeEvent =
393 getItemFromStorageLockedInterruptible(500ms, mUserActivityPokeEvents, lock,
394 mNotifyUserActivity);
395 ASSERT_TRUE(pokeEvent) << "Expected a user poke event";
396
397 if (expectedPokeEvent) {
398 ASSERT_EQ(expectedPokeEvent, *pokeEvent);
399 }
Josep del Riob3981622023-04-18 15:49:45 +0000400 }
401
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000402 void assertNotifyDeviceInteractionWasCalled(int32_t deviceId, std::set<gui::Uid> uids) {
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000403 ASSERT_EQ(std::make_pair(deviceId, uids), mNotifiedInteractions.popWithTimeout(100ms));
404 }
405
406 void assertNotifyDeviceInteractionWasNotCalled() {
407 ASSERT_FALSE(mNotifiedInteractions.popWithTimeout(10ms));
408 }
409
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000410 void setUnhandledKeyHandler(std::function<std::optional<KeyEvent>(const KeyEvent&)> handler) {
411 std::scoped_lock lock(mLock);
412 mUnhandledKeyHandler = handler;
413 }
414
415 void assertUnhandledKeyReported(int32_t keycode) {
416 std::unique_lock lock(mLock);
417 base::ScopedLockAssertion assumeLocked(mLock);
418 std::optional<int32_t> unhandledKeycode =
419 getItemFromStorageLockedInterruptible(100ms, mReportedUnhandledKeycodes, lock,
420 mNotifyUnhandledKey);
421 ASSERT_TRUE(unhandledKeycode) << "Expected unhandled key to be reported";
422 ASSERT_EQ(unhandledKeycode, keycode);
423 }
424
425 void assertUnhandledKeyNotReported() {
426 std::unique_lock lock(mLock);
427 base::ScopedLockAssertion assumeLocked(mLock);
428 std::optional<int32_t> unhandledKeycode =
429 getItemFromStorageLockedInterruptible(10ms, mReportedUnhandledKeycodes, lock,
430 mNotifyUnhandledKey);
431 ASSERT_FALSE(unhandledKeycode) << "Expected unhandled key NOT to be reported";
432 }
433
Michael Wrightd02c5b62014-02-10 15:10:22 -0800434private:
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700435 std::mutex mLock;
436 std::unique_ptr<InputEvent> mFilteredEvent GUARDED_BY(mLock);
437 std::optional<nsecs_t> mConfigurationChangedTime GUARDED_BY(mLock);
438 sp<IBinder> mOnPointerDownToken GUARDED_BY(mLock);
439 std::optional<NotifySwitchArgs> mLastNotifySwitch GUARDED_BY(mLock);
Jackal Guof9696682018-10-05 12:23:23 +0800440
Prabir Pradhan99987712020-11-10 18:43:05 -0800441 std::condition_variable mPointerCaptureChangedCondition;
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000442
443 std::optional<PointerCaptureRequest> mPointerCaptureRequest GUARDED_BY(mLock);
Prabir Pradhan99987712020-11-10 18:43:05 -0800444
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700445 // ANR handling
Chris Yea209fde2020-07-22 13:54:51 -0700446 std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800447 std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock);
448 std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700449 std::condition_variable mNotifyAnr;
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800450 std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock);
451 std::condition_variable mNotifyInputChannelBroken;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700452
arthurhungf452d0b2021-01-06 00:19:52 +0800453 sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
Arthur Hung6d0571e2021-04-09 20:18:16 +0800454 bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -0800455
456 std::condition_variable mNotifyUserActivity;
457 std::queue<UserActivityPokeEvent> mUserActivityPokeEvents;
arthurhungf452d0b2021-01-06 00:19:52 +0800458
Arthur Hung2ee6d0b2022-03-03 20:19:38 +0800459 std::chrono::milliseconds mInterceptKeyTimeout = 0ms;
460
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700461 std::chrono::nanoseconds mStaleEventTimeout = 1000ms;
462
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000463 BlockingQueue<std::pair<int32_t /*deviceId*/, std::set<gui::Uid>>> mNotifiedInteractions;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +0000464
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000465 std::condition_variable mNotifyUnhandledKey;
466 std::queue<int32_t> mReportedUnhandledKeycodes GUARDED_BY(mLock);
467 std::function<std::optional<KeyEvent>(const KeyEvent&)> mUnhandledKeyHandler GUARDED_BY(mLock);
468
Prabir Pradhanedd96402022-02-15 01:46:16 -0800469 // All three ANR-related callbacks behave the same way, so we use this generic function to wait
470 // for a specific container to become non-empty. When the container is non-empty, return the
471 // first entry from the container and erase it.
472 template <class T>
473 T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage,
474 std::unique_lock<std::mutex>& lock) REQUIRES(mLock) {
475 // If there is an ANR, Dispatcher won't be idle because there are still events
476 // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle
477 // before checking if ANR was called.
478 // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need
479 // to provide it some time to act. 100ms seems reasonable.
480 std::chrono::duration timeToWait = timeout + 100ms; // provide some slack
481 const std::chrono::time_point start = std::chrono::steady_clock::now();
482 std::optional<T> token =
483 getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr);
484 if (!token.has_value()) {
485 ADD_FAILURE() << "Did not receive the ANR callback";
486 return {};
487 }
488
489 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
490 // Ensure that the ANR didn't get raised too early. We can't be too strict here because
491 // the dispatcher started counting before this function was called
492 if (std::chrono::abs(timeout - waited) > 100ms) {
493 ADD_FAILURE() << "ANR was raised too early or too late. Expected "
494 << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count()
495 << "ms, but waited "
496 << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count()
497 << "ms instead";
498 }
499 return *token;
500 }
501
502 template <class T>
503 std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout,
504 std::queue<T>& storage,
505 std::unique_lock<std::mutex>& lock,
506 std::condition_variable& condition)
507 REQUIRES(mLock) {
508 condition.wait_for(lock, timeout,
509 [&storage]() REQUIRES(mLock) { return !storage.empty(); });
510 if (storage.empty()) {
Prabir Pradhanedd96402022-02-15 01:46:16 -0800511 return std::nullopt;
512 }
513 T item = storage.front();
514 storage.pop();
515 return std::make_optional(item);
516 }
517
Siarhei Vishniakou2b4782c2020-11-07 01:51:18 -0600518 void notifyConfigurationChanged(nsecs_t when) override {
Siarhei Vishniakoucd899e82020-05-08 09:24:29 -0700519 std::scoped_lock lock(mLock);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800520 mConfigurationChangedTime = when;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800521 }
522
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000523 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
Prabir Pradhanedd96402022-02-15 01:46:16 -0800524 const std::string&) override {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700525 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800526 ASSERT_TRUE(pid.has_value());
527 mAnrWindows.push({connectionToken, *pid});
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700528 mNotifyAnr.notify_all();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500529 }
530
Prabir Pradhanedd96402022-02-15 01:46:16 -0800531 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000532 std::optional<gui::Pid> pid) override {
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500533 std::scoped_lock lock(mLock);
Prabir Pradhanedd96402022-02-15 01:46:16 -0800534 ASSERT_TRUE(pid.has_value());
535 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
663class InputDispatcherTest : public testing::Test {
664protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000665 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700666 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800667
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000668 void SetUp() override {
Prabir Pradhana41d2442023-04-20 21:30:40 +0000669 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhan9fb98f72024-02-02 19:47:19 +0000670 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, nullptr);
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700671
Harry Cutts101ee9b2023-07-06 18:04:14 +0000672 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000673 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700674 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800675 }
676
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000677 void TearDown() override {
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700678 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000679 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700680 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800681 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700682
683 /**
684 * Used for debugging when writing the test
685 */
686 void dumpDispatcherState() {
687 std::string dump;
688 mDispatcher->dump(dump);
689 std::stringstream ss(dump);
690 std::string to;
691
692 while (std::getline(ss, to, '\n')) {
693 ALOGE("%s", to.c_str());
694 }
695 }
Vishnu Nair958da932020-08-21 17:12:37 -0700696
Chavi Weingarten847e8512023-03-29 00:26:09 +0000697 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700698 FocusRequest request;
699 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000700 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700701 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
702 request.displayId = window->getInfo()->displayId;
703 mDispatcher->setFocusedWindow(request);
704 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800705};
706
Michael Wrightd02c5b62014-02-10 15:10:22 -0800707TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
708 KeyEvent event;
709
710 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800711 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
712 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000713 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600714 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800715 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000716 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000717 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800718 << "Should reject key events with undefined action.";
719
720 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800721 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
722 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600723 ARBITRARY_TIME, 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 ACTION_MULTIPLE.";
728}
729
730TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
731 MotionEvent event;
732 PointerProperties pointerProperties[MAX_POINTERS + 1];
733 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800734 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800735 pointerProperties[i].clear();
736 pointerProperties[i].id = i;
737 pointerCoords[i].clear();
738 }
739
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800740 // Some constants commonly used below
741 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
742 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
743 constexpr int32_t metaState = AMETA_NONE;
744 constexpr MotionClassification classification = MotionClassification::NONE;
745
chaviw9eaa22c2020-07-01 16:21:27 -0700746 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800747 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800748 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000749 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700750 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700751 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
752 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000753 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800754 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000755 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000756 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800757 << "Should reject motion events with undefined action.";
758
759 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800760 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800761 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
762 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
763 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
764 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000765 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800766 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000767 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000768 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800769 << "Should reject motion events with pointer down index too large.";
770
Garfield Tanfbe732e2020-01-24 11:26:14 -0800771 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700772 AMOTION_EVENT_ACTION_POINTER_DOWN |
773 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700774 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
775 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700776 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000777 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800778 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000779 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000780 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800781 << "Should reject motion events with pointer down index too small.";
782
783 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800784 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800785 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
786 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
787 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
788 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000789 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800790 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000791 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000792 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800793 << "Should reject motion events with pointer up index too large.";
794
Garfield Tanfbe732e2020-01-24 11:26:14 -0800795 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700796 AMOTION_EVENT_ACTION_POINTER_UP |
797 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700798 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
799 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700800 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000801 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800802 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000803 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000804 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800805 << "Should reject motion events with pointer up index too small.";
806
807 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800808 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
809 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700810 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700811 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
812 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000813 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800814 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000815 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000816 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800817 << "Should reject motion events with 0 pointers.";
818
Garfield Tanfbe732e2020-01-24 11:26:14 -0800819 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
820 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700821 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700822 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
823 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000824 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800825 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000826 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000827 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800828 << "Should reject motion events with more than MAX_POINTERS pointers.";
829
830 // Rejects motion events with invalid pointer ids.
831 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800832 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
833 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700834 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700835 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
836 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000837 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800838 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000839 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000840 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800841 << "Should reject motion events with pointer ids less than 0.";
842
843 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800844 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
845 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700846 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700847 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
848 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000849 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800850 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000851 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000852 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
854
855 // Rejects motion events with duplicate pointer ids.
856 pointerProperties[0].id = 1;
857 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800858 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
859 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700860 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700861 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
862 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000863 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800864 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000865 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000866 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800867 << "Should reject motion events with duplicate pointer ids.";
868}
869
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800870/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
871
872TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
873 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000874 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800875 ASSERT_TRUE(mDispatcher->waitForIdle());
876
877 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
878}
879
880TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000881 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
882 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000883 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000884 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800885
886 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
887 args.policyFlags |= POLICY_FLAG_TRUSTED;
888 mFakePolicy->assertNotifySwitchWasCalled(args);
889}
890
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700891namespace {
892
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700893static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700894// Default input dispatching timeout if there is no focused application or paused window
895// from which to determine an appropriate dispatching timeout.
896static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
897 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
898 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800899
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800900class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800901public:
Garfield Tan15601662020-09-22 15:32:38 -0700902 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700903 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800904
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800905 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
906 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700907 if (!consumeSeq) {
908 return nullptr;
909 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000910 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800911 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700912 }
913
914 /**
915 * Receive an event without acknowledging it.
916 * Return the sequence number that could later be used to send finished signal.
917 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800918 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
919 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800920 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800921 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800922
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800923 std::chrono::time_point start = std::chrono::steady_clock::now();
924 status_t status = WOULD_BLOCK;
925 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800926 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700927 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800928 &rawEventPtr);
929 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800930 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700931 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800932 break;
933 }
934 }
935
936 if (status == WOULD_BLOCK) {
937 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800938 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800939 }
940
941 if (status != OK) {
942 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800943 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800944 }
945 if (event == nullptr) {
946 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800947 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800948 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700949 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800950
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700951 /**
952 * To be used together with "receiveEvent" to complete the consumption of an event.
953 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000954 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700955 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700956 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800957 }
958
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000959 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700960 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000961 ASSERT_EQ(OK, status);
962 }
963
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700964 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000965 std::optional<int32_t> expectedDisplayId,
966 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800967 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800968
969 ASSERT_NE(nullptr, event) << mName.c_str()
970 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800971 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700972 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
973 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800974
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000975 if (expectedDisplayId.has_value()) {
976 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
977 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800978
Tiger Huang8664f8c2018-10-11 19:14:35 +0800979 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700980 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800981 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700982 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000983 if (expectedFlags.has_value()) {
984 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
985 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800986 break;
987 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700988 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800989 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700990 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000991 if (expectedFlags.has_value()) {
992 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
993 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800994 break;
995 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700996 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100997 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
998 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700999 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -08001000 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
1001 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001002 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001003 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
1004 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001005 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +08001006 FAIL() << "Use 'consumeDragEvent' for DRAG events";
1007 }
Tiger Huang8664f8c2018-10-11 19:14:35 +08001008 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001009 }
1010
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001011 std::unique_ptr<MotionEvent> consumeMotion() {
1012 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001013
1014 if (event == nullptr) {
1015 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
1016 return nullptr;
1017 }
1018
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001019 if (event->getType() != InputEventType::MOTION) {
1020 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001021 return nullptr;
1022 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001023 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001024 }
1025
1026 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001027 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001028 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
1029 ASSERT_THAT(*motionEvent, matcher);
1030 }
1031
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001032 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001033 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001034 ASSERT_NE(nullptr, event) << mName.c_str()
1035 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001036 ASSERT_EQ(InputEventType::FOCUS, event->getType())
1037 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001038
1039 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1040 << mName.c_str() << ": event displayId should always be NONE.";
1041
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001042 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1043 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001044 }
1045
Prabir Pradhan99987712020-11-10 18:43:05 -08001046 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001047 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -08001048 ASSERT_NE(nullptr, event) << mName.c_str()
1049 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001050 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
1051 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -08001052
1053 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1054 << mName.c_str() << ": event displayId should always be NONE.";
1055
1056 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
1057 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
1058 }
1059
arthurhungb89ccb02020-12-30 16:19:01 +08001060 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001061 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +08001062 ASSERT_NE(nullptr, event) << mName.c_str()
1063 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001064 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +08001065
1066 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1067 << mName.c_str() << ": event displayId should always be NONE.";
1068
1069 const auto& dragEvent = static_cast<const DragEvent&>(*event);
1070 EXPECT_EQ(isExiting, dragEvent.isExiting());
1071 EXPECT_EQ(x, dragEvent.getX());
1072 EXPECT_EQ(y, dragEvent.getY());
1073 }
1074
Antonio Kantekf16f2832021-09-28 04:39:20 +00001075 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001076 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +00001077 ASSERT_NE(nullptr, event) << mName.c_str()
1078 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001079 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
1080 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +00001081
1082 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
1083 << mName.c_str() << ": event displayId should always be NONE.";
1084 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
1085 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
1086 }
1087
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001088 void assertNoEvents(std::chrono::milliseconds timeout) {
1089 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001090 if (event == nullptr) {
1091 return;
1092 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001093 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001094 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001095 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001096 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001097 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001098 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001099 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001100 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
1101 ADD_FAILURE() << "Received focus event, hasFocus = "
1102 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001103 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -08001104 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
1105 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
1106 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07001107 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +00001108 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
1109 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
1110 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001111 }
1112 FAIL() << mName.c_str()
1113 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -08001114 }
1115
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001116 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -08001117
Siarhei Vishniakou8d660132024-01-11 16:48:44 -08001118 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001119
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001120private:
1121 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001122 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -08001123
1124 std::string mName;
1125};
1126
chaviw3277faf2021-05-19 16:45:23 -05001127class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -08001128public:
1129 static const int32_t WIDTH = 600;
1130 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -08001131
Chris Yea209fde2020-07-22 13:54:51 -07001132 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -07001133 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001134 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -08001135 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001136 sp<IBinder> token;
1137 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -07001138 base::Result<std::unique_ptr<InputChannel>> channel =
1139 dispatcher->createInputChannel(name);
1140 token = (*channel)->getConnectionToken();
1141 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -08001142 }
1143
1144 inputApplicationHandle->updateInfo();
1145 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
1146
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001147 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001148 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -08001149 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001150 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001151 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +00001152 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -07001153 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -08001154 mInfo.globalScaleFactor = 1.0;
1155 mInfo.touchableRegion.clear();
1156 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +00001157 mInfo.ownerPid = WINDOW_PID;
1158 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -08001159 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001160 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -08001161 }
1162
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07001163 sp<FakeWindowHandle> clone(int32_t displayId) {
1164 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
1165 handle->mInfo = mInfo;
1166 handle->mInfo.displayId = displayId;
1167 handle->mInfo.id = sId++;
1168 handle->mInputReceiver = mInputReceiver;
1169 return handle;
1170 }
1171
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001172 void setTouchable(bool touchable) {
1173 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
1174 }
chaviwd1c23182019-12-20 18:44:56 -08001175
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001176 void setFocusable(bool focusable) {
1177 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
1178 }
1179
1180 void setVisible(bool visible) {
1181 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
1182 }
Vishnu Nair958da932020-08-21 17:12:37 -07001183
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001184 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -05001185 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001186 }
1187
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001188 void setPaused(bool paused) {
1189 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
1190 }
1191
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001192 void setPreventSplitting(bool preventSplitting) {
1193 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001194 }
1195
1196 void setSlippery(bool slippery) {
1197 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
1198 }
1199
1200 void setWatchOutsideTouch(bool watchOutside) {
1201 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
1202 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001203
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001204 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
1205
1206 void setInterceptsStylus(bool interceptsStylus) {
1207 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
1208 }
1209
1210 void setDropInput(bool dropInput) {
1211 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
1212 }
1213
1214 void setDropInputIfObscured(bool dropInputIfObscured) {
1215 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
1216 }
1217
1218 void setNoInputChannel(bool noInputChannel) {
1219 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
1220 }
1221
Josep del Riob3981622023-04-18 15:49:45 +00001222 void setDisableUserActivity(bool disableUserActivity) {
1223 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
1224 }
1225
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07001226 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
1227 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
1228 shouldGlobalStylusBlockTouch);
1229 }
1230
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001231 void setAlpha(float alpha) { mInfo.alpha = alpha; }
1232
chaviw3277faf2021-05-19 16:45:23 -05001233 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001234
Bernardo Rufino7393d172021-02-26 13:56:11 +00001235 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
1236
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001237 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +00001238 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -08001239 mInfo.touchableRegion.clear();
1240 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001241
1242 const Rect logicalDisplayFrame = displayTransform.transform(frame);
1243 ui::Transform translate;
1244 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
1245 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -08001246 }
1247
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001248 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
1249
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001250 void setIsWallpaper(bool isWallpaper) {
1251 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
1252 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001253
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001254 void setDupTouchToWallpaper(bool hasWallpaper) {
1255 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
1256 }
chaviwd1c23182019-12-20 18:44:56 -08001257
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001258 void setTrustedOverlay(bool trustedOverlay) {
1259 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
1260 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001261
chaviw9eaa22c2020-07-01 16:21:27 -07001262 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
1263 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
1264 }
1265
1266 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -07001267
yunho.shinf4a80b82020-11-16 21:13:57 +09001268 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
1269
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001270 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
1271 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
1272 if (event == nullptr) {
1273 ADD_FAILURE() << "No event";
1274 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001275 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001276 if (event->getType() != InputEventType::KEY) {
1277 ADD_FAILURE() << "Instead of key event, got " << event;
1278 return nullptr;
1279 }
1280 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001281 }
1282
1283 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001284 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
1285 ASSERT_NE(nullptr, keyEvent);
1286 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001287 }
1288
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001289 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001290 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
1291 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001292 }
1293
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001294 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001295 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1296 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001297 }
1298
Svet Ganov5d3bc372020-01-26 23:11:07 -08001299 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001300 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001301 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
1302 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001303 }
1304
1305 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001306 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08001307 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
1308 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001309 }
1310
1311 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001312 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00001313 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
1314 }
1315
1316 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
1317 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001318 consumeMotionEvent(
1319 AllOf(WithMotionAction(ACTION_DOWN),
1320 testing::Conditional(expectedDisplayId.has_value(),
1321 WithDisplayId(*expectedDisplayId), testing::_),
1322 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
1323 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001324 }
1325
Svet Ganov5d3bc372020-01-26 23:11:07 -08001326 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001327 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1328 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001329 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001330 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001331 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1332 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001333 }
1334
1335 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001336 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001337 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001338 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001339 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
1340 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08001341 }
1342
1343 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001344 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001345 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
1346 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +00001347 }
1348
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001349 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
1350 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001351 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
1352 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05001353 }
1354
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001355 void consumeMotionOutsideWithZeroedCoords() {
1356 consumeMotionEvent(
1357 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08001358 }
1359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001360 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
1361 ASSERT_NE(mInputReceiver, nullptr)
1362 << "Cannot consume events from a window with no receiver";
1363 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
1364 }
1365
Prabir Pradhan99987712020-11-10 18:43:05 -08001366 void consumeCaptureEvent(bool hasCapture) {
1367 ASSERT_NE(mInputReceiver, nullptr)
1368 << "Cannot consume events from a window with no receiver";
1369 mInputReceiver->consumeCaptureEvent(hasCapture);
1370 }
1371
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001372 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001373 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001374 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
1375 if (event == nullptr) {
1376 ADD_FAILURE() << "No event";
1377 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +00001378 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001379 if (event->getType() != InputEventType::MOTION) {
1380 ADD_FAILURE() << "Instead of motion event, got " << *event;
1381 return nullptr;
1382 }
1383 std::unique_ptr<MotionEvent> motionEvent =
1384 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
1385 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001386 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -08001387 }
1388
arthurhungb89ccb02020-12-30 16:19:01 +08001389 void consumeDragEvent(bool isExiting, float x, float y) {
1390 mInputReceiver->consumeDragEvent(isExiting, x, y);
1391 }
1392
Antonio Kantekf16f2832021-09-28 04:39:20 +00001393 void consumeTouchModeEvent(bool inTouchMode) {
1394 ASSERT_NE(mInputReceiver, nullptr)
1395 << "Cannot consume events from a window with no receiver";
1396 mInputReceiver->consumeTouchModeEvent(inTouchMode);
1397 }
1398
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001399 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhan9fb98f72024-02-02 19:47:19 +00001400 if (mInputReceiver == nullptr) {
1401 ADD_FAILURE() << "Invalid receive event on window with no receiver";
1402 return std::make_pair(std::nullopt, nullptr);
1403 }
1404 return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001405 }
1406
1407 void finishEvent(uint32_t sequenceNum) {
1408 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1409 mInputReceiver->finishEvent(sequenceNum);
1410 }
1411
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00001412 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
1413 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
1414 mInputReceiver->sendTimeline(inputEventId, timeline);
1415 }
1416
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001417 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001418 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -08001419 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05001420 return; // Can't receive events if the window does not have input channel
1421 }
1422 ASSERT_NE(nullptr, mInputReceiver)
1423 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001424 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +08001425 }
1426
chaviwaf87b3e2019-10-01 16:59:28 -07001427 sp<IBinder> getToken() { return mInfo.token; }
1428
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01001429 const std::string& getName() { return mName; }
1430
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001431 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001432 mInfo.ownerPid = ownerPid;
1433 mInfo.ownerUid = ownerUid;
1434 }
1435
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00001436 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -08001437
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001438 void destroyReceiver() { mInputReceiver = nullptr; }
1439
Prabir Pradhan07e05b62021-11-19 03:57:24 -08001440 int getChannelFd() { return mInputReceiver->getChannelFd(); }
1441
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001442 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001443 if (mInputReceiver == nullptr) {
1444 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
1445 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001446 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001447 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001448 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001449 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001450 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00001451 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001452
1453private:
1454 FakeWindowHandle(std::string name) : mName(name){};
1455 const std::string mName;
1456 std::shared_ptr<FakeInputReceiver> mInputReceiver;
1457 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
1458 friend class sp<FakeWindowHandle>;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08001459};
1460
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -07001461std::atomic<int32_t> FakeWindowHandle::sId{1};
1462
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001463class FakeMonitorReceiver {
1464public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001465 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1466 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001467
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001468 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001469
1470 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001471 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1472 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001473 }
1474
1475 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001476 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1477 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001478 }
1479
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001480 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001481
1482 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001483 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1484 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001485 }
1486
1487 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001488 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1489 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001490 }
1491
1492 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001493 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1494 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001495 }
1496
1497 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001498 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001499 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1500 WithDisplayId(expectedDisplayId),
1501 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1502 }
1503
1504 void consumeMotionPointerDown(int32_t pointerIdx) {
1505 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1506 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001507 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1508 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001509 }
1510
1511 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001512 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001513 }
1514
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001515 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001516
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001517 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001518
1519private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001520 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001521};
1522
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001523static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001524 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001525 int32_t displayId = ADISPLAY_ID_NONE,
1526 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001527 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001528 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001529 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001530 KeyEvent event;
1531 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1532
1533 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001534 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001535 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1536 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001537
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001538 if (!allowKeyRepeat) {
1539 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1540 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001541 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001542 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001543}
1544
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001545static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1546 InputEventInjectionResult result =
1547 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1548 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1549 if (result != InputEventInjectionResult::TIMED_OUT) {
1550 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1551 }
1552}
1553
1554static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001555 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001556 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001557}
1558
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001559// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1560// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1561// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001562static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1563 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001564 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001565 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001566 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001567}
1568
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001569static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001570 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001571 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001572}
1573
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001574static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001575 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001576 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001577 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001578 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001579 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1580 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001581}
1582
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001583static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001584 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1585 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001586 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001587 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1588 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001589 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001590 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001591 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001592 MotionEventBuilder motionBuilder =
1593 MotionEventBuilder(action, source)
1594 .displayId(displayId)
1595 .eventTime(eventTime)
1596 .rawXCursorPosition(cursorPosition.x)
1597 .rawYCursorPosition(cursorPosition.y)
1598 .pointer(
1599 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1600 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1601 motionBuilder.downTime(eventTime);
1602 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001603
1604 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001605 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1606 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001607}
1608
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001609static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1610 int32_t displayId,
1611 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001612 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001613}
1614
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001615static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1616 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001617 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001618 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001619}
1620
Jackal Guof9696682018-10-05 12:23:23 +08001621static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1622 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1623 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001624 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1625 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1626 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001627
1628 return args;
1629}
1630
Josep del Riob3981622023-04-18 15:49:45 +00001631static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1632 int32_t displayId = ADISPLAY_ID_NONE) {
1633 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1634 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001635 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1636 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1637 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001638
1639 return args;
1640}
1641
1642static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1643 int32_t displayId = ADISPLAY_ID_NONE) {
1644 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1645 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001646 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1647 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1648 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001649
1650 return args;
1651}
1652
Prabir Pradhan678438e2023-04-13 19:32:51 +00001653[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1654 int32_t displayId,
1655 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001656 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001657 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1658 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1659 }
1660
chaviwd1c23182019-12-20 18:44:56 -08001661 PointerProperties pointerProperties[pointerCount];
1662 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001663
chaviwd1c23182019-12-20 18:44:56 -08001664 for (size_t i = 0; i < pointerCount; i++) {
1665 pointerProperties[i].clear();
1666 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001667 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001668
chaviwd1c23182019-12-20 18:44:56 -08001669 pointerCoords[i].clear();
1670 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1671 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1672 }
Jackal Guof9696682018-10-05 12:23:23 +08001673
1674 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1675 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001676 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1677 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1678 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001679 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001680 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001681 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001682 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001683
1684 return args;
1685}
1686
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001687static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1688 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1689}
1690
chaviwd1c23182019-12-20 18:44:56 -08001691static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1692 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1693}
1694
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001695static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1696 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001697 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1698 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001699}
1700
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001701} // namespace
1702
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001703/**
1704 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1705 * broken channel.
1706 */
1707TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1708 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1709 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001710 sp<FakeWindowHandle>::make(application, mDispatcher,
1711 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001712
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001713 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001714
1715 // Window closes its channel, but the window remains.
1716 window->destroyReceiver();
1717 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1718}
1719
Arthur Hungb92218b2018-08-14 12:00:21 +08001720TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1723 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001724
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001725 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001728 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001729
1730 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001731 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001732}
1733
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001734using InputDispatcherDeathTest = InputDispatcherTest;
1735
1736/**
1737 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1738 * should crash.
1739 */
1740TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1741 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1742 ScopedSilentDeath _silentDeath;
1743
1744 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1745 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1746 "Fake Window", ADISPLAY_ID_DEFAULT);
1747 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1748 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1749 "Incorrect WindowInfosUpdate provided");
1750}
1751
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001752TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001754 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1755 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001758 // Inject a MotionEvent to an unknown display.
1759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001761 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1762
1763 // Window should receive motion event.
1764 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1765}
1766
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001767/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001768 * Calling onWindowInfosChanged once should not cause any issues.
1769 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001770 * called twice.
1771 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001772TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001774 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1775 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001776 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001777
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001778 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001781 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001783
1784 // Window should receive motion event.
1785 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1786}
1787
1788/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001789 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001790 */
1791TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001792 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);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001795 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001796
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001797 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1798 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001800 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001801 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001803
1804 // Window should receive motion event.
1805 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1806}
1807
Arthur Hungb92218b2018-08-14 12:00:21 +08001808// The foreground window should receive the first touch down event.
1809TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001810 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001811 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001812 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001813 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001814 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001815
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001816 mDispatcher->onWindowInfosChanged(
1817 {{*windowTop->getInfo(), *windowSecond->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 Vishniakouae6229e2019-12-30 16:23:19 -08001820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001821
1822 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001823 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001824 windowSecond->assertNoEvents();
1825}
1826
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001827/**
1828 * Two windows: A top window, and a wallpaper behind the window.
1829 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1830 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001831 * 1. foregroundWindow <-- dup touch to wallpaper
1832 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001833 */
1834TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1836 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001837 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001838 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001839 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001840 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001841 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001842
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001843 mDispatcher->onWindowInfosChanged(
1844 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001846 injectMotionEvent(*mDispatcher,
1847 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1848 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1849 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1851
1852 // Both foreground window and its wallpaper should receive the touch down
1853 foregroundWindow->consumeMotionDown();
1854 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1855
1856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001857 injectMotionEvent(*mDispatcher,
1858 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1859 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1860 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001861 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1862
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001863 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001864 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1865
1866 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001867 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001868 foregroundWindow->consumeMotionCancel();
1869 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1870 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1871}
1872
1873/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001874 * Two fingers down on the window, and lift off the first finger.
1875 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1876 * contains a single pointer.
1877 */
1878TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1880 sp<FakeWindowHandle> window =
1881 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1882
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001883 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001884 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1886 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1887 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001888 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001889 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1890 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1891 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1892 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001893 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001894 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1895 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1896 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1897 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001898 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1899 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1900 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1901
1902 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001903 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001904 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1905 window->consumeMotionEvent(
1906 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1907}
1908
1909/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001910 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1911 * with the following differences:
1912 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1913 * clean up the connection.
1914 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1915 * Ensure that there's no crash in the dispatcher.
1916 */
1917TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1918 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1919 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001920 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001921 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001922 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001923 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001924 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001926 mDispatcher->onWindowInfosChanged(
1927 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001929 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001930 {100, 200}))
1931 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1932
1933 // Both foreground window and its wallpaper should receive the touch down
1934 foregroundWindow->consumeMotionDown();
1935 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1936
1937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001938 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001939 ADISPLAY_ID_DEFAULT, {110, 200}))
1940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1941
1942 foregroundWindow->consumeMotionMove();
1943 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1944
1945 // Wallpaper closes its channel, but the window remains.
1946 wallpaperWindow->destroyReceiver();
1947 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1948
1949 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1950 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001951 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001952 foregroundWindow->consumeMotionCancel();
1953}
1954
Arthur Hungc539dbb2022-12-08 07:45:36 +00001955class ShouldSplitTouchFixture : public InputDispatcherTest,
1956 public ::testing::WithParamInterface<bool> {};
1957INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1958 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001959/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001960 * A single window that receives touch (on top), and a wallpaper window underneath it.
1961 * The top window gets a multitouch gesture.
1962 * Ensure that wallpaper gets the same gesture.
1963 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001964TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001966 sp<FakeWindowHandle> foregroundWindow =
1967 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1968 foregroundWindow->setDupTouchToWallpaper(true);
1969 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001970
1971 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001972 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001973 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001974
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001975 mDispatcher->onWindowInfosChanged(
1976 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001977
1978 // Touch down on top window
1979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001980 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001981 {100, 100}))
1982 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1983
1984 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001985 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001986 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1987
1988 // Second finger down on the top window
1989 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001990 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001991 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001992 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1993 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001994 .build();
1995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001996 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001997 InputEventInjectionSync::WAIT_FOR_RESULT))
1998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1999
Harry Cutts33476232023-01-30 19:57:29 +00002000 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
2001 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002002 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00002003
2004 const MotionEvent secondFingerUpEvent =
2005 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2006 .displayId(ADISPLAY_ID_DEFAULT)
2007 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002008 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2009 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002010 .build();
2011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002012 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002013 InputEventInjectionSync::WAIT_FOR_RESULT))
2014 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2015 foregroundWindow->consumeMotionPointerUp(0);
2016 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2017
2018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002019 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002020 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2021 AINPUT_SOURCE_TOUCHSCREEN)
2022 .displayId(ADISPLAY_ID_DEFAULT)
2023 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00002024 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08002025 .x(100)
2026 .y(100))
2027 .build(),
2028 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00002029 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2030 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
2031 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002032}
2033
2034/**
2035 * Two windows: a window on the left and window on the right.
2036 * A third window, wallpaper, is behind both windows, and spans both top windows.
2037 * The first touch down goes to the left window. A second pointer touches down on the right window.
2038 * The touch is split, so both left and right windows should receive ACTION_DOWN.
2039 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
2040 * ACTION_POINTER_DOWN(1).
2041 */
2042TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
2043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2044 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002045 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002046 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002047 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002048
2049 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002050 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002051 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002052 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002053
2054 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07002055 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002056 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08002057 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002058
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002059 mDispatcher->onWindowInfosChanged(
2060 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2061 {},
2062 0,
2063 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002064
2065 // Touch down on left window
2066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002068 {100, 100}))
2069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2070
2071 // Both foreground window and its wallpaper should receive the touch down
2072 leftWindow->consumeMotionDown();
2073 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2074
2075 // Second finger down on the right window
2076 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002077 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002078 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002079 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2080 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002081 .build();
2082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002083 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002084 InputEventInjectionSync::WAIT_FOR_RESULT))
2085 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2086
2087 leftWindow->consumeMotionMove();
2088 // Since the touch is split, right window gets ACTION_DOWN
2089 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00002090 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002091 expectedWallpaperFlags);
2092
2093 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002094 mDispatcher->onWindowInfosChanged(
2095 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002096 leftWindow->consumeMotionCancel();
2097 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
2098 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2099
2100 // The pointer that's still down on the right window moves, and goes to the right window only.
2101 // As far as the dispatcher's concerned though, both pointers are still present.
2102 const MotionEvent secondFingerMoveEvent =
2103 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2104 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07002105 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
2106 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002107 .build();
2108 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002109 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00002110 InputEventInjectionSync::WAIT_FOR_RESULT));
2111 rightWindow->consumeMotionMove();
2112
2113 leftWindow->assertNoEvents();
2114 rightWindow->assertNoEvents();
2115 wallpaperWindow->assertNoEvents();
2116}
2117
Arthur Hungc539dbb2022-12-08 07:45:36 +00002118/**
2119 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
2120 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
2121 * The right window should receive ACTION_DOWN.
2122 */
2123TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00002124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00002125 sp<FakeWindowHandle> leftWindow =
2126 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2127 leftWindow->setFrame(Rect(0, 0, 200, 200));
2128 leftWindow->setDupTouchToWallpaper(true);
2129 leftWindow->setSlippery(true);
2130
2131 sp<FakeWindowHandle> rightWindow =
2132 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2133 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00002134
2135 sp<FakeWindowHandle> wallpaperWindow =
2136 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
2137 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00002138
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002139 mDispatcher->onWindowInfosChanged(
2140 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
2141 {},
2142 0,
2143 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00002144
Arthur Hungc539dbb2022-12-08 07:45:36 +00002145 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00002146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002147 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002148 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002149 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00002150
2151 // Both foreground window and its wallpaper should receive the touch down
2152 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00002153 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
2154
Arthur Hungc539dbb2022-12-08 07:45:36 +00002155 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00002156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002157 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00002158 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00002159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
2160
Arthur Hungc539dbb2022-12-08 07:45:36 +00002161 leftWindow->consumeMotionCancel();
2162 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
2163 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00002164}
2165
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08002166/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002167 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2168 * interactive, it might stop sending this flag.
2169 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
2170 * to have a consistent input stream.
2171 *
2172 * Test procedure:
2173 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
2174 * DOWN (new gesture).
2175 *
2176 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
2177 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
2178 *
2179 * We technically just need a single window here, but we are using two windows (spy on top and a
2180 * regular window below) to emulate the actual situation where it happens on the device.
2181 */
2182TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
2183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2184 sp<FakeWindowHandle> spyWindow =
2185 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2186 spyWindow->setFrame(Rect(0, 0, 200, 200));
2187 spyWindow->setTrustedOverlay(true);
2188 spyWindow->setSpy(true);
2189
2190 sp<FakeWindowHandle> window =
2191 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2192 window->setFrame(Rect(0, 0, 200, 200));
2193
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002194 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002195 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002196
2197 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002198 mDispatcher->notifyMotion(
2199 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2200 .deviceId(touchDeviceId)
2201 .policyFlags(DEFAULT_POLICY_FLAGS)
2202 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2203 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002204
Prabir Pradhan678438e2023-04-13 19:32:51 +00002205 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2206 .deviceId(touchDeviceId)
2207 .policyFlags(DEFAULT_POLICY_FLAGS)
2208 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2209 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2210 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002211 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2212 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2213 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2214 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2215
2216 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002217 mDispatcher->notifyMotion(
2218 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
2219 .deviceId(touchDeviceId)
2220 .policyFlags(0)
2221 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2222 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
2223 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002224 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2225 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
2226
2227 // We don't need to reset the device to reproduce the issue, but the reset event typically
2228 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002229 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002230
2231 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00002232 mDispatcher->notifyMotion(
2233 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2234 .deviceId(touchDeviceId)
2235 .policyFlags(DEFAULT_POLICY_FLAGS)
2236 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
2237 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08002238 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2239 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2240
2241 // No more events
2242 spyWindow->assertNoEvents();
2243 window->assertNoEvents();
2244}
2245
2246/**
Linnan Li907ae732023-09-05 17:14:21 +08002247 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
2248 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
2249 * interactive, it might stop sending this flag.
2250 * We've already ensured the consistency of the touch event in this case, and we should also ensure
2251 * the consistency of the hover event in this case.
2252 *
2253 * Test procedure:
2254 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
2255 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
2256 *
2257 * We expect to receive two full streams of hover events.
2258 */
2259TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
2260 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2261
2262 sp<FakeWindowHandle> window =
2263 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2264 window->setFrame(Rect(0, 0, 300, 300));
2265
2266 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2267
2268 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2269 .policyFlags(DEFAULT_POLICY_FLAGS)
2270 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2271 .build());
2272 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2273
2274 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2275 .policyFlags(DEFAULT_POLICY_FLAGS)
2276 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2277 .build());
2278 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2279
2280 // Send hover exit without the default policy flags.
2281 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2282 .policyFlags(0)
2283 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2284 .build());
2285
2286 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2287
2288 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
2289 // right event.
2290 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2291 .policyFlags(DEFAULT_POLICY_FLAGS)
2292 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
2293 .build());
2294 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2295
2296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2297 .policyFlags(DEFAULT_POLICY_FLAGS)
2298 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2299 .build());
2300 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2301
2302 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2303 .policyFlags(DEFAULT_POLICY_FLAGS)
2304 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
2305 .build());
2306 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2307}
2308
2309/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002310 * Two windows: a window on the left and a window on the right.
2311 * Mouse is hovered from the right window into the left window.
2312 * Next, we tap on the left window, where the cursor was last seen.
2313 * The second tap is done onto the right window.
2314 * The mouse and tap are from two different devices.
2315 * We technically don't need to set the downtime / eventtime for these events, but setting these
2316 * explicitly helps during debugging.
2317 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2318 * In the buggy implementation, a tap on the right window would cause a crash.
2319 */
2320TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
2321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2322 sp<FakeWindowHandle> leftWindow =
2323 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2324 leftWindow->setFrame(Rect(0, 0, 200, 200));
2325
2326 sp<FakeWindowHandle> rightWindow =
2327 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2328 rightWindow->setFrame(Rect(200, 0, 400, 200));
2329
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002330 mDispatcher->onWindowInfosChanged(
2331 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002332 // All times need to start at the current time, otherwise the dispatcher will drop the events as
2333 // stale.
2334 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
2335 const int32_t mouseDeviceId = 6;
2336 const int32_t touchDeviceId = 4;
2337 // Move the cursor from right
2338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2341 AINPUT_SOURCE_MOUSE)
2342 .deviceId(mouseDeviceId)
2343 .downTime(baseTime + 10)
2344 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002345 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002346 .build()));
2347 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2348
2349 // .. to the left window
2350 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002351 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002352 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2353 AINPUT_SOURCE_MOUSE)
2354 .deviceId(mouseDeviceId)
2355 .downTime(baseTime + 10)
2356 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002357 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002358 .build()));
2359 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2360 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2361 // Now tap the left window
2362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002363 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002364 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2365 AINPUT_SOURCE_TOUCHSCREEN)
2366 .deviceId(touchDeviceId)
2367 .downTime(baseTime + 40)
2368 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002369 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002370 .build()));
2371 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2372 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2373
2374 // release tap
2375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002376 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002377 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2378 AINPUT_SOURCE_TOUCHSCREEN)
2379 .deviceId(touchDeviceId)
2380 .downTime(baseTime + 40)
2381 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002382 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002383 .build()));
2384 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2385
2386 // Tap the window on the right
2387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002388 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002389 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2390 AINPUT_SOURCE_TOUCHSCREEN)
2391 .deviceId(touchDeviceId)
2392 .downTime(baseTime + 60)
2393 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002394 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002395 .build()));
2396 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2397
2398 // release tap
2399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002400 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002401 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2402 AINPUT_SOURCE_TOUCHSCREEN)
2403 .deviceId(touchDeviceId)
2404 .downTime(baseTime + 60)
2405 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002406 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08002407 .build()));
2408 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2409
2410 // No more events
2411 leftWindow->assertNoEvents();
2412 rightWindow->assertNoEvents();
2413}
2414
2415/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002416 * Start hovering in a window. While this hover is still active, make another window appear on top.
2417 * The top, obstructing window has no input channel, so it's not supposed to receive input.
2418 * While the top window is present, the hovering is stopped.
2419 * Later, hovering gets resumed again.
2420 * Ensure that new hover gesture is handled correctly.
2421 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
2422 * to the window that's currently being hovered over.
2423 */
2424TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
2425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2426 sp<FakeWindowHandle> window =
2427 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2428 window->setFrame(Rect(0, 0, 200, 200));
2429
2430 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002431 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002432
2433 // Start hovering in the window
2434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2436 .build());
2437 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2438
2439 // Now, an obscuring window appears!
2440 sp<FakeWindowHandle> obscuringWindow =
2441 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2442 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002443 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002444 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2445 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2446 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2447 obscuringWindow->setNoInputChannel(true);
2448 obscuringWindow->setFocusable(false);
2449 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002450 mDispatcher->onWindowInfosChanged(
2451 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002452
2453 // While this new obscuring window is present, the hovering is stopped
2454 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
2455 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2456 .build());
2457 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2458
2459 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002460 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002461
2462 // And a new hover gesture starts.
2463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2464 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2465 .build());
2466 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2467}
2468
2469/**
2470 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2471 * the obscuring window.
2472 */
2473TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2475 sp<FakeWindowHandle> window =
2476 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2477 window->setFrame(Rect(0, 0, 200, 200));
2478
2479 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002480 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002481
2482 // Start hovering in the window
2483 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2484 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2485 .build());
2486 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2487
2488 // Now, an obscuring window appears!
2489 sp<FakeWindowHandle> obscuringWindow =
2490 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2491 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002492 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002493 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2494 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2495 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2496 obscuringWindow->setNoInputChannel(true);
2497 obscuringWindow->setFocusable(false);
2498 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002499 mDispatcher->onWindowInfosChanged(
2500 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002501
2502 // While this new obscuring window is present, the hovering continues. The event can't go to the
2503 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2504 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2505 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2506 .build());
2507 obscuringWindow->assertNoEvents();
2508 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2509
2510 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002511 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002512
2513 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2514 // so it should generate a HOVER_ENTER
2515 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2516 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2517 .build());
2518 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2519
2520 // Now the MOVE should be getting dispatched normally
2521 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2522 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2523 .build());
2524 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2525}
2526
2527/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002528 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2529 * events are delivered to the window.
2530 */
2531TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2533 sp<FakeWindowHandle> window =
2534 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2535 window->setFrame(Rect(0, 0, 200, 200));
2536 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2537
2538 // Start hovering in the window
2539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2540 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2541 .build());
2542 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2543
2544 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2545 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2546 .build());
2547 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2548
2549 // Scroll with the mouse
2550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2551 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2552 .build());
2553 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2554}
2555
2556using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2557
2558/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002559 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2560 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002561 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002562TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2564 sp<FakeWindowHandle> window =
2565 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2566 window->setFrame(Rect(0, 0, 200, 200));
2567
2568 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2569
2570 constexpr int32_t touchDeviceId = 4;
2571 constexpr int32_t stylusDeviceId = 2;
2572
2573 // Stylus down
2574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2575 .deviceId(stylusDeviceId)
2576 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2577 .build());
2578 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2579
2580 // Touch down
2581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2582 .deviceId(touchDeviceId)
2583 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2584 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002585
2586 // Touch move
2587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2588 .deviceId(touchDeviceId)
2589 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2590 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002591 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002592
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002593 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002594 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2595 .deviceId(stylusDeviceId)
2596 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2597 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002598 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2599 WithCoords(101, 111)));
2600
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002601 window->assertNoEvents();
2602}
2603
2604/**
2605 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002606 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002607 * Similar test as above, but with added SPY window.
2608 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002609TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002610 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2611 sp<FakeWindowHandle> window =
2612 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2613 sp<FakeWindowHandle> spyWindow =
2614 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2615 spyWindow->setFrame(Rect(0, 0, 200, 200));
2616 spyWindow->setTrustedOverlay(true);
2617 spyWindow->setSpy(true);
2618 window->setFrame(Rect(0, 0, 200, 200));
2619
2620 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2621
2622 constexpr int32_t touchDeviceId = 4;
2623 constexpr int32_t stylusDeviceId = 2;
2624
2625 // Stylus down
2626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2627 .deviceId(stylusDeviceId)
2628 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2629 .build());
2630 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2631 spyWindow->consumeMotionEvent(
2632 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2633
2634 // Touch down
2635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2636 .deviceId(touchDeviceId)
2637 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2638 .build());
2639
2640 // Touch move
2641 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2642 .deviceId(touchDeviceId)
2643 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2644 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002645
2646 // Touch is ignored because stylus is already down
2647
2648 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2650 .deviceId(stylusDeviceId)
2651 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2652 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002653 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2654 WithCoords(101, 111)));
2655 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2656 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002657
2658 window->assertNoEvents();
2659 spyWindow->assertNoEvents();
2660}
2661
2662/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002663 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002664 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002665 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002666TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002667 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2668 sp<FakeWindowHandle> window =
2669 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2670 window->setFrame(Rect(0, 0, 200, 200));
2671
2672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2673
2674 constexpr int32_t touchDeviceId = 4;
2675 constexpr int32_t stylusDeviceId = 2;
2676
2677 // Stylus down on the window
2678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2679 .deviceId(stylusDeviceId)
2680 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2681 .build());
2682 window->consumeMotionEvent(
2683 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2684
2685 // Touch down on window
2686 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2687 .deviceId(touchDeviceId)
2688 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2689 .build());
2690 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2691 .deviceId(touchDeviceId)
2692 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2693 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002694
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002695 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002696
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002697 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002698 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2699 .deviceId(stylusDeviceId)
2700 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2701 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002702 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2703 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002704
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002705 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2707 .deviceId(touchDeviceId)
2708 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2709 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002710 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002711}
2712
2713/**
2714 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002715 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002716 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002717TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2719 sp<FakeWindowHandle> window =
2720 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2721 window->setFrame(Rect(0, 0, 200, 200));
2722
2723 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2724
2725 constexpr int32_t touchDeviceId = 4;
2726 constexpr int32_t stylusDeviceId = 2;
2727
2728 // Touch down on window
2729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2730 .deviceId(touchDeviceId)
2731 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2732 .build());
2733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2734 .deviceId(touchDeviceId)
2735 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2736 .build());
2737 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2738 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2739
2740 // Stylus hover on the window
2741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2742 .deviceId(stylusDeviceId)
2743 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2744 .build());
2745 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2746 .deviceId(stylusDeviceId)
2747 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2748 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002749 // Stylus hover movement causes touch to be canceled
2750 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2751 WithCoords(141, 146)));
2752 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2753 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2754 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2755 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002756
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002757 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2759 .deviceId(touchDeviceId)
2760 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2761 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002762
2763 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002764}
2765
2766/**
2767 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2768 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2769 * become active.
2770 */
2771TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2773 sp<FakeWindowHandle> window =
2774 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2775 window->setFrame(Rect(0, 0, 200, 200));
2776
2777 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2778
2779 constexpr int32_t stylusDeviceId1 = 3;
2780 constexpr int32_t stylusDeviceId2 = 5;
2781
2782 // Touch down on window
2783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2784 .deviceId(stylusDeviceId1)
2785 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2786 .build());
2787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2788 .deviceId(stylusDeviceId1)
2789 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2790 .build());
2791 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2792 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2793
2794 // Second stylus down
2795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2796 .deviceId(stylusDeviceId2)
2797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2798 .build());
2799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2800 .deviceId(stylusDeviceId2)
2801 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2802 .build());
2803
2804 // First stylus is canceled, second one takes over.
2805 window->consumeMotionEvent(
2806 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2807 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2808 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2809
2810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2811 .deviceId(stylusDeviceId1)
2812 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2813 .build());
2814 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002815 window->assertNoEvents();
2816}
2817
2818/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002819 * One window. Touch down on the window. Then, stylus down on the window from another device.
2820 * Ensure that is canceled, because stylus down should be preferred over touch.
2821 */
2822TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2824 sp<FakeWindowHandle> window =
2825 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2826 window->setFrame(Rect(0, 0, 200, 200));
2827
2828 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2829
2830 constexpr int32_t touchDeviceId = 4;
2831 constexpr int32_t stylusDeviceId = 2;
2832
2833 // Touch down on window
2834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2835 .deviceId(touchDeviceId)
2836 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2837 .build());
2838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2839 .deviceId(touchDeviceId)
2840 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2841 .build());
2842 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2843 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2844
2845 // Stylus down on the window
2846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2847 .deviceId(stylusDeviceId)
2848 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2849 .build());
2850 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2851 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2852
2853 // Subsequent stylus movements are delivered correctly
2854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2855 .deviceId(stylusDeviceId)
2856 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2857 .build());
2858 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2859 WithCoords(101, 111)));
2860}
2861
2862/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002863 * Two windows: a window on the left and a window on the right.
2864 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2865 * down. Then, on the left window, also place second touch pointer down.
2866 * This test tries to reproduce a crash.
2867 * In the buggy implementation, second pointer down on the left window would cause a crash.
2868 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002869TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2871 sp<FakeWindowHandle> leftWindow =
2872 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2873 leftWindow->setFrame(Rect(0, 0, 200, 200));
2874
2875 sp<FakeWindowHandle> rightWindow =
2876 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2877 rightWindow->setFrame(Rect(200, 0, 400, 200));
2878
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002879 mDispatcher->onWindowInfosChanged(
2880 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002881
2882 const int32_t touchDeviceId = 4;
2883 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002884
2885 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2887 .deviceId(mouseDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2889 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002890 leftWindow->consumeMotionEvent(
2891 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2892
2893 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2895 .deviceId(mouseDeviceId)
2896 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2897 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2898 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002899
2900 leftWindow->consumeMotionEvent(
2901 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2902 leftWindow->consumeMotionEvent(
2903 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2904
Prabir Pradhan678438e2023-04-13 19:32:51 +00002905 mDispatcher->notifyMotion(
2906 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2907 .deviceId(mouseDeviceId)
2908 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2909 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2910 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2911 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002912 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2913
2914 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2916 .deviceId(touchDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2918 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 leftWindow->assertNoEvents();
2920
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002921 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2922
2923 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002924 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2925 .deviceId(touchDeviceId)
2926 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2927 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2928 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002929 // Since this is now a new splittable pointer going down on the left window, and it's coming
2930 // from a different device, the current gesture in the left window (pointer down) should first
2931 // be canceled.
2932 leftWindow->consumeMotionEvent(
2933 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002934 leftWindow->consumeMotionEvent(
2935 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2936 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2937 // current implementation.
2938 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2939 rightWindow->consumeMotionEvent(
2940 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2941
2942 leftWindow->assertNoEvents();
2943 rightWindow->assertNoEvents();
2944}
2945
2946/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002947 * Two windows: a window on the left and a window on the right.
2948 * Mouse is hovered on the left window and stylus is hovered on the right window.
2949 */
2950TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2952 sp<FakeWindowHandle> leftWindow =
2953 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2954 leftWindow->setFrame(Rect(0, 0, 200, 200));
2955
2956 sp<FakeWindowHandle> rightWindow =
2957 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2958 rightWindow->setFrame(Rect(200, 0, 400, 200));
2959
2960 mDispatcher->onWindowInfosChanged(
2961 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2962
2963 const int32_t stylusDeviceId = 3;
2964 const int32_t mouseDeviceId = 6;
2965
2966 // Start hovering over the left window
2967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2968 .deviceId(mouseDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2970 .build());
2971 leftWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2973
2974 // Stylus hovered on right window
2975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2976 .deviceId(stylusDeviceId)
2977 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2978 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979 rightWindow->consumeMotionEvent(
2980 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2981
2982 // Subsequent HOVER_MOVE events are dispatched correctly.
2983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2984 .deviceId(mouseDeviceId)
2985 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2986 .build());
2987 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002988 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989
2990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2991 .deviceId(stylusDeviceId)
2992 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2993 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002994 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002995 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002996
2997 leftWindow->assertNoEvents();
2998 rightWindow->assertNoEvents();
2999}
3000
3001/**
3002 * Three windows: a window on the left and a window on the right.
3003 * And a spy window that's positioned above all of them.
3004 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
3005 * Check the stream that's received by the spy.
3006 */
3007TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
3008 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3009
3010 sp<FakeWindowHandle> spyWindow =
3011 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3012 spyWindow->setFrame(Rect(0, 0, 400, 400));
3013 spyWindow->setTrustedOverlay(true);
3014 spyWindow->setSpy(true);
3015
3016 sp<FakeWindowHandle> leftWindow =
3017 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3018 leftWindow->setFrame(Rect(0, 0, 200, 200));
3019
3020 sp<FakeWindowHandle> rightWindow =
3021 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3022
3023 rightWindow->setFrame(Rect(200, 0, 400, 200));
3024
3025 mDispatcher->onWindowInfosChanged(
3026 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3027
3028 const int32_t stylusDeviceId = 1;
3029 const int32_t touchDeviceId = 2;
3030
3031 // Stylus down on the left window
3032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3033 .deviceId(stylusDeviceId)
3034 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3035 .build());
3036 leftWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3038 spyWindow->consumeMotionEvent(
3039 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3040
3041 // Touch down on the right window
3042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3043 .deviceId(touchDeviceId)
3044 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3045 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003046 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003047 rightWindow->consumeMotionEvent(
3048 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003049
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003050 // Spy window does not receive touch events, because stylus events take precedence, and it
3051 // already has an active stylus gesture.
3052
3053 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3055 .deviceId(stylusDeviceId)
3056 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3057 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003058 leftWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3060 spyWindow->consumeMotionEvent(
3061 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003062
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003063 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3065 .deviceId(touchDeviceId)
3066 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3067 .build());
3068 rightWindow->consumeMotionEvent(
3069 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003070
3071 spyWindow->assertNoEvents();
3072 leftWindow->assertNoEvents();
3073 rightWindow->assertNoEvents();
3074}
3075
3076/**
3077 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3078 * both.
3079 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003080 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003081 * At the same time, left and right should be getting independent streams of hovering and touch,
3082 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003083 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003084TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3086
3087 sp<FakeWindowHandle> spyWindow =
3088 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3089 spyWindow->setFrame(Rect(0, 0, 400, 400));
3090 spyWindow->setTrustedOverlay(true);
3091 spyWindow->setSpy(true);
3092
3093 sp<FakeWindowHandle> leftWindow =
3094 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3095 leftWindow->setFrame(Rect(0, 0, 200, 200));
3096
3097 sp<FakeWindowHandle> rightWindow =
3098 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3099 rightWindow->setFrame(Rect(200, 0, 400, 200));
3100
3101 mDispatcher->onWindowInfosChanged(
3102 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3103
3104 const int32_t stylusDeviceId = 1;
3105 const int32_t touchDeviceId = 2;
3106
3107 // Stylus hover on the left window
3108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3109 .deviceId(stylusDeviceId)
3110 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3111 .build());
3112 leftWindow->consumeMotionEvent(
3113 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3114 spyWindow->consumeMotionEvent(
3115 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3116
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003117 // Touch down on the right window. Spy doesn't receive this touch because it already has
3118 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3120 .deviceId(touchDeviceId)
3121 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3122 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003123 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003124 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003125 rightWindow->consumeMotionEvent(
3126 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3127
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003128 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3130 .deviceId(stylusDeviceId)
3131 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3132 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003133 leftWindow->consumeMotionEvent(
3134 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003135 spyWindow->consumeMotionEvent(
3136 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003137
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003138 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003139 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3140 .deviceId(touchDeviceId)
3141 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3142 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003143 rightWindow->consumeMotionEvent(
3144 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3145
3146 spyWindow->assertNoEvents();
3147 leftWindow->assertNoEvents();
3148 rightWindow->assertNoEvents();
3149}
3150
3151/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003152 * On a single window, use two different devices: mouse and touch.
3153 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3154 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3155 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3156 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3157 * represent a new gesture.
3158 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003159TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003160 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3161 sp<FakeWindowHandle> window =
3162 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3163 window->setFrame(Rect(0, 0, 400, 400));
3164
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003165 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003166
3167 const int32_t touchDeviceId = 4;
3168 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003169
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003170 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3172 .deviceId(touchDeviceId)
3173 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3174 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003175 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003176 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3177 .deviceId(touchDeviceId)
3178 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3179 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3180 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003181 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003182 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3183 .deviceId(touchDeviceId)
3184 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3185 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3186 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003187 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3188 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3189 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3190
3191 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003192 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3193 .deviceId(mouseDeviceId)
3194 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3195 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3196 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197
3198 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003199 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003200 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3201
Prabir Pradhan678438e2023-04-13 19:32:51 +00003202 mDispatcher->notifyMotion(
3203 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3204 .deviceId(mouseDeviceId)
3205 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3206 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3207 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3208 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003209 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3210
3211 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003212 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3213 .deviceId(touchDeviceId)
3214 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3215 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3216 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003217 // Since we already canceled this touch gesture, it will be ignored until a completely new
3218 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3219 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3220 // However, mouse movements should continue to work.
3221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3222 .deviceId(mouseDeviceId)
3223 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3224 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3225 .build());
3226 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3227
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003228 window->assertNoEvents();
3229}
3230
3231/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003232 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3233 * the injected event.
3234 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003235TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003236 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3237 sp<FakeWindowHandle> window =
3238 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3239 window->setFrame(Rect(0, 0, 400, 400));
3240
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003241 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003242
3243 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003244 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3245 // completion.
3246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003247 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003248 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3249 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003250 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003251 .build()));
3252 window->consumeMotionEvent(
3253 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3254
3255 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3256 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3258 .deviceId(touchDeviceId)
3259 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3260 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003261
3262 window->consumeMotionEvent(
3263 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3264 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3265}
3266
3267/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003268 * This test is similar to the test above, but the sequence of injected events is different.
3269 *
3270 * Two windows: a window on the left and a window on the right.
3271 * Mouse is hovered over the left window.
3272 * Next, we tap on the left window, where the cursor was last seen.
3273 *
3274 * After that, we inject one finger down onto the right window, and then a second finger down onto
3275 * the left window.
3276 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3277 * window (first), and then another on the left window (second).
3278 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3279 * In the buggy implementation, second finger down on the left window would cause a crash.
3280 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003281TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3283 sp<FakeWindowHandle> leftWindow =
3284 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
3285 leftWindow->setFrame(Rect(0, 0, 200, 200));
3286
3287 sp<FakeWindowHandle> rightWindow =
3288 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
3289 rightWindow->setFrame(Rect(200, 0, 400, 200));
3290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003291 mDispatcher->onWindowInfosChanged(
3292 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003293
3294 const int32_t mouseDeviceId = 6;
3295 const int32_t touchDeviceId = 4;
3296 // Hover over the left window. Keep the cursor there.
3297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003298 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003299 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3300 AINPUT_SOURCE_MOUSE)
3301 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003302 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003303 .build()));
3304 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3305
3306 // Tap on left window
3307 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003308 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003309 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3310 AINPUT_SOURCE_TOUCHSCREEN)
3311 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003312 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003313 .build()));
3314
3315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003316 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003317 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3318 AINPUT_SOURCE_TOUCHSCREEN)
3319 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003320 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003321 .build()));
3322 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3323 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3324 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3325
3326 // First finger down on right window
3327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003328 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003329 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3330 AINPUT_SOURCE_TOUCHSCREEN)
3331 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003332 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003333 .build()));
3334 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3335
3336 // Second finger down on the left window
3337 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003338 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003339 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3340 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3342 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003343 .build()));
3344 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3345 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3346
3347 // No more events
3348 leftWindow->assertNoEvents();
3349 rightWindow->assertNoEvents();
3350}
3351
3352/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003353 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3354 * While the touch is down, new hover events from the stylus device should be ignored. After the
3355 * touch is gone, stylus hovering should start working again.
3356 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003357TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3359 sp<FakeWindowHandle> window =
3360 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3361 window->setFrame(Rect(0, 0, 200, 200));
3362
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003364
3365 const int32_t stylusDeviceId = 5;
3366 const int32_t touchDeviceId = 4;
3367 // Start hovering with stylus
3368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003369 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003370 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003371 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003372 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003373 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003374 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003375
3376 // Finger down on the window
3377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003378 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003379 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003380 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003381 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003382 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003383 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003384
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003385 // Continue hovering with stylus.
3386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003387 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003388 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3389 AINPUT_SOURCE_STYLUS)
3390 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003391 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003392 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003393 // Hovers continue to work
3394 window->consumeMotionEvent(
3395 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003396
3397 // Lift up the finger
3398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003399 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003400 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3401 AINPUT_SOURCE_TOUCHSCREEN)
3402 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003403 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003404 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003405
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003407 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003408 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3409 AINPUT_SOURCE_STYLUS)
3410 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003411 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003412 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003413 window->consumeMotionEvent(
3414 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003415 window->assertNoEvents();
3416}
3417
3418/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003419 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3420 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3421 *
3422 * Two windows: one on the left and one on the right.
3423 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3424 * Stylus down on the left window, and then touch down on the right window.
3425 * Check that the right window doesn't get touches while the stylus is down on the left window.
3426 */
3427TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3429 sp<FakeWindowHandle> leftWindow =
3430 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3431 ADISPLAY_ID_DEFAULT);
3432 leftWindow->setFrame(Rect(0, 0, 100, 100));
3433
3434 sp<FakeWindowHandle> sbtRightWindow =
3435 sp<FakeWindowHandle>::make(application, mDispatcher,
3436 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3437 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3438 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3439
3440 mDispatcher->onWindowInfosChanged(
3441 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3442
3443 const int32_t stylusDeviceId = 5;
3444 const int32_t touchDeviceId = 4;
3445
3446 // Stylus down in the left window
3447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3448 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3449 .deviceId(stylusDeviceId)
3450 .build());
3451 leftWindow->consumeMotionEvent(
3452 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3453
3454 // Finger tap on the right window
3455 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3456 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3457 .deviceId(touchDeviceId)
3458 .build());
3459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3460 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3461 .deviceId(touchDeviceId)
3462 .build());
3463
3464 // The touch should be blocked, because stylus is down somewhere else on screen!
3465 sbtRightWindow->assertNoEvents();
3466
3467 // Continue stylus motion, and ensure it's not impacted.
3468 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3469 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3470 .deviceId(stylusDeviceId)
3471 .build());
3472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3473 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3474 .deviceId(stylusDeviceId)
3475 .build());
3476 leftWindow->consumeMotionEvent(
3477 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3478 leftWindow->consumeMotionEvent(
3479 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3480
3481 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3483 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3484 .deviceId(touchDeviceId)
3485 .build());
3486 sbtRightWindow->consumeMotionEvent(
3487 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3488}
3489
3490/**
3491 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3492 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3493 *
3494 * Two windows: one on the left and one on the right.
3495 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3496 * Stylus hover on the left window, and then touch down on the right window.
3497 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3498 */
3499TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3501 sp<FakeWindowHandle> leftWindow =
3502 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3503 ADISPLAY_ID_DEFAULT);
3504 leftWindow->setFrame(Rect(0, 0, 100, 100));
3505
3506 sp<FakeWindowHandle> sbtRightWindow =
3507 sp<FakeWindowHandle>::make(application, mDispatcher,
3508 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3509 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3510 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3511
3512 mDispatcher->onWindowInfosChanged(
3513 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3514
3515 const int32_t stylusDeviceId = 5;
3516 const int32_t touchDeviceId = 4;
3517
3518 // Stylus hover in the left window
3519 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3520 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3521 .deviceId(stylusDeviceId)
3522 .build());
3523 leftWindow->consumeMotionEvent(
3524 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3525
3526 // Finger tap on the right window
3527 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3528 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3529 .deviceId(touchDeviceId)
3530 .build());
3531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3532 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3533 .deviceId(touchDeviceId)
3534 .build());
3535
3536 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3537 sbtRightWindow->assertNoEvents();
3538
3539 // Continue stylus motion, and ensure it's not impacted.
3540 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3542 .deviceId(stylusDeviceId)
3543 .build());
3544 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3545 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3546 .deviceId(stylusDeviceId)
3547 .build());
3548 leftWindow->consumeMotionEvent(
3549 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3550 leftWindow->consumeMotionEvent(
3551 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3552
3553 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3555 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3556 .deviceId(touchDeviceId)
3557 .build());
3558 sbtRightWindow->consumeMotionEvent(
3559 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3560}
3561
3562/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003563 * A spy window above a window with no input channel.
3564 * Start hovering with a stylus device, and then tap with it.
3565 * Ensure spy window receives the entire sequence.
3566 */
3567TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3568 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3569 sp<FakeWindowHandle> spyWindow =
3570 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3571 spyWindow->setFrame(Rect(0, 0, 200, 200));
3572 spyWindow->setTrustedOverlay(true);
3573 spyWindow->setSpy(true);
3574 sp<FakeWindowHandle> window =
3575 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3576 window->setNoInputChannel(true);
3577 window->setFrame(Rect(0, 0, 200, 200));
3578
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003579 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003580
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003581 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3584 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003585 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3586 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3588 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3589 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003590 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3591
3592 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3594 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3595 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003596 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3597
3598 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3601 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003602 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3603
3604 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3606 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3607 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003608 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3609 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3611 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3612 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003613 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3614
3615 // No more events
3616 spyWindow->assertNoEvents();
3617 window->assertNoEvents();
3618}
3619
3620/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003621 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3622 * rejected. But since we already have an ongoing gesture, this event should be processed.
3623 * This prevents inconsistent events being handled inside the dispatcher.
3624 */
3625TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3627
3628 sp<FakeWindowHandle> window =
3629 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3630 window->setFrame(Rect(0, 0, 200, 200));
3631
3632 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3633
3634 // Start hovering with stylus
3635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3636 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3637 .build());
3638 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3639
3640 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3641 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3642 .build();
3643 // Make this 'hoverExit' event stale
3644 mFakePolicy->setStaleEventTimeout(100ms);
3645 std::this_thread::sleep_for(100ms);
3646
3647 // It shouldn't be dropped by the dispatcher, even though it's stale.
3648 mDispatcher->notifyMotion(hoverExit);
3649 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3650
3651 // Stylus starts hovering again! There should be no crash.
3652 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3653 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3654 .build());
3655 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3656}
3657
3658/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003659 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3660 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3661 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3662 * While the mouse is down, new move events from the touch device should be ignored.
3663 */
3664TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3666 sp<FakeWindowHandle> spyWindow =
3667 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3668 spyWindow->setFrame(Rect(0, 0, 200, 200));
3669 spyWindow->setTrustedOverlay(true);
3670 spyWindow->setSpy(true);
3671 sp<FakeWindowHandle> window =
3672 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3673 window->setFrame(Rect(0, 0, 200, 200));
3674
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003675 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003676
3677 const int32_t mouseDeviceId = 7;
3678 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003679
3680 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003681 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3682 .deviceId(mouseDeviceId)
3683 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3684 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003685 spyWindow->consumeMotionEvent(
3686 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3687 window->consumeMotionEvent(
3688 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3689
3690 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003691 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3692 .deviceId(touchDeviceId)
3693 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3694 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003695 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3696 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3697 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3698 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3699
Prabir Pradhan678438e2023-04-13 19:32:51 +00003700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3701 .deviceId(touchDeviceId)
3702 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3703 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003704 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3705 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3706
3707 // Pilfer the stream
3708 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3709 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3710
Prabir Pradhan678438e2023-04-13 19:32:51 +00003711 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3712 .deviceId(touchDeviceId)
3713 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3714 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003715 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3716
3717 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3719 .deviceId(mouseDeviceId)
3720 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3721 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3722 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003723
3724 spyWindow->consumeMotionEvent(
3725 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3726 spyWindow->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3728 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3729
Prabir Pradhan678438e2023-04-13 19:32:51 +00003730 mDispatcher->notifyMotion(
3731 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3732 .deviceId(mouseDeviceId)
3733 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3734 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3735 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3736 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003737 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3738 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3739
3740 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3742 .deviceId(mouseDeviceId)
3743 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3744 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3745 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003746 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3747 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3748
3749 // Touch move!
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(65).y(65))
3753 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754
3755 // No more events
3756 spyWindow->assertNoEvents();
3757 window->assertNoEvents();
3758}
3759
3760/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003761 * On the display, have a single window, and also an area where there's no window.
3762 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3763 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3764 */
3765TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3766 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3767 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003768 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003769
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003770 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003771
3772 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003773 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003774
3775 mDispatcher->waitForIdle();
3776 window->assertNoEvents();
3777
3778 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003779 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003780 mDispatcher->waitForIdle();
3781 window->consumeMotionDown();
3782}
3783
3784/**
3785 * Same test as above, but instead of touching the empty space, the first touch goes to
3786 * non-touchable window.
3787 */
3788TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3789 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3790 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003791 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003792 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3793 window1->setTouchable(false);
3794 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003795 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003796 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3797
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003798 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003799
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003800 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003801 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003802
3803 mDispatcher->waitForIdle();
3804 window1->assertNoEvents();
3805 window2->assertNoEvents();
3806
3807 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003809 mDispatcher->waitForIdle();
3810 window2->consumeMotionDown();
3811}
3812
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003813/**
3814 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3815 * to the event time of the first ACTION_DOWN sent to the particular window.
3816 */
3817TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3819 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003820 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003821 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3822 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003823 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003824 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3825
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003826 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003827
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003828 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003829 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003830
3831 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003832
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003833 std::unique_ptr<MotionEvent> motionEvent1 = window1->consumeMotionEvent();
3834 ASSERT_NE(nullptr, motionEvent1);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003835 window2->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003836 nsecs_t downTimeForWindow1 = motionEvent1->getDownTime();
3837 ASSERT_EQ(motionEvent1->getDownTime(), motionEvent1->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003838
3839 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003840 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003841 mDispatcher->waitForIdle();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003842 std::unique_ptr<MotionEvent> motionEvent2 = window2->consumeMotionEvent();
3843 ASSERT_NE(nullptr, motionEvent2);
3844 nsecs_t downTimeForWindow2 = motionEvent2->getDownTime();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003845 ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08003846 ASSERT_EQ(motionEvent2->getDownTime(), motionEvent2->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003847
3848 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003849 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003850 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003851 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003852
3853 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003854 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003855 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003856 window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003857
3858 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
3859 window1->consumeMotionMove();
3860 window1->assertNoEvents();
3861
3862 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003863 mDispatcher->notifyMotion(
3864 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003865 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003866 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003867
Prabir Pradhan678438e2023-04-13 19:32:51 +00003868 mDispatcher->notifyMotion(
3869 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003870 mDispatcher->waitForIdle();
Siarhei Vishniakoue9349e72022-12-02 11:39:20 -08003871 window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003872}
3873
Garfield Tandf26e862020-07-01 20:18:19 -07003874TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003875 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003876 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003877 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003878 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003879 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003880 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003881 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003882
3883 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3884
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003885 mDispatcher->onWindowInfosChanged(
3886 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003887
3888 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003890 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003891 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3892 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003893 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003894 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003895 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003896
3897 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003899 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003900 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3901 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003902 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003903 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003904 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3905 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003906
3907 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003909 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003910 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3911 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003912 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003913 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003914 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3915 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003916
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003918 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003919 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3920 AINPUT_SOURCE_MOUSE)
3921 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3922 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003923 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003924 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003925 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003926
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003928 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003929 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3930 AINPUT_SOURCE_MOUSE)
3931 .buttonState(0)
3932 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003934 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003935 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003936
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_UP, AINPUT_SOURCE_MOUSE)
3940 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003942 .build()));
3943 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3944
3945 // Move mouse cursor back to right 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(900).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_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003953
3954 // No more events
3955 windowLeft->assertNoEvents();
3956 windowRight->assertNoEvents();
3957}
3958
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003959/**
3960 * Put two fingers down (and don't release them) and click the mouse button.
3961 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3962 * currently active gesture should be canceled, and the new one should proceed.
3963 */
3964TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3966 sp<FakeWindowHandle> window =
3967 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3968 window->setFrame(Rect(0, 0, 600, 800));
3969
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003970 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003971
3972 const int32_t touchDeviceId = 4;
3973 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003974
3975 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3977 .deviceId(touchDeviceId)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3979 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003980
Prabir Pradhan678438e2023-04-13 19:32:51 +00003981 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3982 .deviceId(touchDeviceId)
3983 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3984 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3985 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003986 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3987 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3988
3989 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3991 .deviceId(mouseDeviceId)
3992 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3993 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3994 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3996 WithPointerCount(2u)));
3997 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3998
Prabir Pradhan678438e2023-04-13 19:32:51 +00003999 mDispatcher->notifyMotion(
4000 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4001 .deviceId(mouseDeviceId)
4002 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4003 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4004 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4005 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004006 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4007
4008 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4009 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004010 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4011 .deviceId(touchDeviceId)
4012 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4013 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4014 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004015 window->assertNoEvents();
4016}
4017
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004018TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4020
4021 sp<FakeWindowHandle> spyWindow =
4022 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4023 spyWindow->setFrame(Rect(0, 0, 600, 800));
4024 spyWindow->setTrustedOverlay(true);
4025 spyWindow->setSpy(true);
4026 sp<FakeWindowHandle> window =
4027 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4028 window->setFrame(Rect(0, 0, 600, 800));
4029
4030 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004031 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004032
4033 // Send mouse cursor to the window
4034 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004035 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004036 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4037 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004038 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004039 .build()));
4040
4041 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4042 WithSource(AINPUT_SOURCE_MOUSE)));
4043 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4044 WithSource(AINPUT_SOURCE_MOUSE)));
4045
4046 window->assertNoEvents();
4047 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004048}
4049
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004050TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4051 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4052
4053 sp<FakeWindowHandle> spyWindow =
4054 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4055 spyWindow->setFrame(Rect(0, 0, 600, 800));
4056 spyWindow->setTrustedOverlay(true);
4057 spyWindow->setSpy(true);
4058 sp<FakeWindowHandle> window =
4059 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4060 window->setFrame(Rect(0, 0, 600, 800));
4061
4062 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004063 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004064
4065 // Send mouse cursor to the window
4066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004067 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004068 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4069 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004070 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004071 .build()));
4072
4073 // Move mouse cursor
4074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004075 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004076 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4077 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004078 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004079 .build()));
4080
4081 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4082 WithSource(AINPUT_SOURCE_MOUSE)));
4083 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4084 WithSource(AINPUT_SOURCE_MOUSE)));
4085 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4086 WithSource(AINPUT_SOURCE_MOUSE)));
4087 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4088 WithSource(AINPUT_SOURCE_MOUSE)));
4089 // Touch down on the window
4090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004091 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004092 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4093 AINPUT_SOURCE_TOUCHSCREEN)
4094 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004095 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004096 .build()));
4097 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4098 WithSource(AINPUT_SOURCE_MOUSE)));
4099 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4100 WithSource(AINPUT_SOURCE_MOUSE)));
4101 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4102 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4103 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4104 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4105
4106 // pilfer the motion, retaining the gesture on the spy window.
4107 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4108 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4109 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4110
4111 // Touch UP on the window
4112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004113 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004114 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4115 AINPUT_SOURCE_TOUCHSCREEN)
4116 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004117 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004118 .build()));
4119 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4120 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4121
4122 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4123 // to send a new gesture. It should again go to both windows (spy and the window below), just
4124 // like the first gesture did, before pilfering. The window configuration has not changed.
4125
4126 // One more tap - DOWN
4127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004128 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004129 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4130 AINPUT_SOURCE_TOUCHSCREEN)
4131 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004132 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004133 .build()));
4134 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4135 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4136 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4137 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4138
4139 // Touch UP on the window
4140 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004141 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004142 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4143 AINPUT_SOURCE_TOUCHSCREEN)
4144 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004145 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004146 .build()));
4147 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4148 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4149 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4150 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4151
4152 window->assertNoEvents();
4153 spyWindow->assertNoEvents();
4154}
4155
Garfield Tandf26e862020-07-01 20:18:19 -07004156// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4157// directly in this test.
4158TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004159 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07004160 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004161 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004162 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004163
4164 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4165
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004166 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004167
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004169 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004170 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4171 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004172 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004173 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004174 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004175 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004177 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004178 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4179 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004180 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004181 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004182 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4183 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004184
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004186 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004187 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4188 AINPUT_SOURCE_MOUSE)
4189 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4190 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004191 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004192 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004193 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004194
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004195 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004196 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004197 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4198 AINPUT_SOURCE_MOUSE)
4199 .buttonState(0)
4200 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004201 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004202 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004203 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004204
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004206 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004207 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4208 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004209 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004210 .build()));
4211 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
4212
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004213 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4214 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4215 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004216 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004217 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4218 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004219 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004220 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004221 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004222}
4223
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004224/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004225 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4226 * is generated.
4227 */
4228TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4230 sp<FakeWindowHandle> window =
4231 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4232 window->setFrame(Rect(0, 0, 1200, 800));
4233
4234 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4235
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004236 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004237
4238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004239 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004240 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4241 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004243 .build()));
4244 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4245
4246 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004247 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004248 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4249}
4250
4251/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004252 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4253 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004254TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4255 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4256 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004257 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4258 sp<FakeWindowHandle> window =
4259 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4260 window->setFrame(Rect(0, 0, 1200, 800));
4261
4262 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4263
4264 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4265
4266 MotionEventBuilder hoverEnterBuilder =
4267 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4268 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4269 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4271 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4273 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4274 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4275 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4276}
4277
4278/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004279 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4280 */
4281TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4282 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4283 sp<FakeWindowHandle> window =
4284 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4285 window->setFrame(Rect(0, 0, 100, 100));
4286
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004287 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004288
4289 const int32_t mouseDeviceId = 7;
4290 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004291
4292 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4294 .deviceId(mouseDeviceId)
4295 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4296 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004297 window->consumeMotionEvent(
4298 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4299
4300 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004301 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4302 .deviceId(touchDeviceId)
4303 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4304 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004305
4306 window->consumeMotionEvent(
4307 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4308 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4309}
4310
4311/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004312 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004313 * The tap causes a HOVER_EXIT event to be generated because the current event
4314 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004315 */
4316TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4318 sp<FakeWindowHandle> window =
4319 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4320 window->setFrame(Rect(0, 0, 100, 100));
4321
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004322 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4324 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4325 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004326 ASSERT_NO_FATAL_FAILURE(
4327 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4328 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004329
4330 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004331 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4332 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4333 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004334 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004335 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4336 WithSource(AINPUT_SOURCE_MOUSE))));
4337
4338 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004339 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4340 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4341
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4343 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4344 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004345 ASSERT_NO_FATAL_FAILURE(
4346 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4347 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4348}
4349
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004350TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4352 sp<FakeWindowHandle> windowDefaultDisplay =
4353 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4354 ADISPLAY_ID_DEFAULT);
4355 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4356 sp<FakeWindowHandle> windowSecondDisplay =
4357 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4358 SECOND_DISPLAY_ID);
4359 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004361 mDispatcher->onWindowInfosChanged(
4362 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004363
4364 // Set cursor position in window in default display and check that hover enter and move
4365 // events are generated.
4366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004367 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004368 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4369 AINPUT_SOURCE_MOUSE)
4370 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004371 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004372 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004373 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004374
4375 // Remove all windows in secondary display and check that no event happens on window in
4376 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004377 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4378
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004379 windowDefaultDisplay->assertNoEvents();
4380
4381 // Move cursor position in window in default display and check that only hover move
4382 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004383 mDispatcher->onWindowInfosChanged(
4384 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004386 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004387 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4388 AINPUT_SOURCE_MOUSE)
4389 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004390 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004391 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004392 windowDefaultDisplay->consumeMotionEvent(
4393 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4394 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004395 windowDefaultDisplay->assertNoEvents();
4396}
4397
Garfield Tan00f511d2019-06-12 16:55:40 -07004398TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004400
4401 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004402 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004403 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004404 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004405 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004406 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004407
4408 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
4409
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004410 mDispatcher->onWindowInfosChanged(
4411 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004412
4413 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4414 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004416 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07004417 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08004418 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004419 windowRight->assertNoEvents();
4420}
4421
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004422TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004423 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004424 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4425 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004426 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004427
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004428 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004429 setFocusedWindow(window);
4430
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004431 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004432
Prabir Pradhan678438e2023-04-13 19:32:51 +00004433 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004434
4435 // Window should receive key down event.
4436 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4437
4438 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4439 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004440 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00004441 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004442}
4443
4444TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004445 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004446 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4447 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004448
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004449 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004450
Prabir Pradhan678438e2023-04-13 19:32:51 +00004451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004453
4454 // Window should receive motion down event.
4455 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4456
4457 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4458 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004459 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004460 window->consumeMotionEvent(
4461 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004462}
4463
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004464TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4465 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4466 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4467 "Fake Window", ADISPLAY_ID_DEFAULT);
4468
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004470
4471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4473 .build());
4474
4475 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4476
4477 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4478 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4479 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4480
4481 // After the device has been reset, a new hovering stream can be sent to the window
4482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4484 .build());
4485 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4486}
4487
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004488TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4489 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004490 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4491 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004492 window->setFocusable(true);
4493
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004494 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004495 setFocusedWindow(window);
4496
4497 window->consumeFocusEvent(true);
4498
Prabir Pradhan678438e2023-04-13 19:32:51 +00004499 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004500 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4501 const nsecs_t injectTime = keyArgs.eventTime;
4502 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004503 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004504 // The dispatching time should be always greater than or equal to intercept key timeout.
4505 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4506 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4507 std::chrono::nanoseconds(interceptKeyTimeout).count());
4508}
4509
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004510/**
4511 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4512 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004513TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004515 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4516 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004517 window->setFocusable(true);
4518
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004519 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004520 setFocusedWindow(window);
4521
4522 window->consumeFocusEvent(true);
4523
Prabir Pradhan678438e2023-04-13 19:32:51 +00004524 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004525 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004526
4527 // Set a value that's significantly larger than the default consumption timeout. If the
4528 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4529 mFakePolicy->setInterceptKeyTimeout(600ms);
4530 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4531 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004532 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4533}
4534
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004535/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004536 * Two windows. First is a regular window. Second does not overlap with the first, and has
4537 * WATCH_OUTSIDE_TOUCH.
4538 * Both windows are owned by the same UID.
4539 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4540 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4541 */
4542TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004544 sp<FakeWindowHandle> window =
4545 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004546 window->setFrame(Rect{0, 0, 100, 100});
4547
4548 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004549 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004550 ADISPLAY_ID_DEFAULT);
4551 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4552 outsideWindow->setWatchOutsideTouch(true);
4553 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004554 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004555
4556 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004557 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4558 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4559 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004560 window->consumeMotionDown();
4561 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4562 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4563 outsideWindow->consumeMotionEvent(
4564 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004565
4566 // Ensure outsideWindow doesn't get any more events for the gesture.
4567 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4568 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4569 window->consumeMotionMove();
4570 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004571}
4572
4573/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004574 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4575 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4576 * ACTION_OUTSIDE event is sent per gesture.
4577 */
4578TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4579 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4580 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004581 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4582 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004583 window->setWatchOutsideTouch(true);
4584 window->setFrame(Rect{0, 0, 100, 100});
4585 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004586 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4587 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004588 secondWindow->setFrame(Rect{100, 100, 200, 200});
4589 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004590 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4591 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004592 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004593 mDispatcher->onWindowInfosChanged(
4594 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004595
4596 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004597 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4598 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4599 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004600 window->assertNoEvents();
4601 secondWindow->assertNoEvents();
4602
4603 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4604 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004605 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4606 ADISPLAY_ID_DEFAULT,
4607 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004608 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4609 window->consumeMotionEvent(
4610 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004611 secondWindow->consumeMotionDown();
4612 thirdWindow->assertNoEvents();
4613
4614 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4615 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004616 mDispatcher->notifyMotion(
4617 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4618 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004619 window->assertNoEvents();
4620 secondWindow->consumeMotionMove();
4621 thirdWindow->consumeMotionDown();
4622}
4623
Prabir Pradhan814fe082022-07-22 20:22:18 +00004624TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4625 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004626 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4627 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004628 window->setFocusable(true);
4629
Patrick Williamsd828f302023-04-28 17:52:08 -05004630 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004631 setFocusedWindow(window);
4632
4633 window->consumeFocusEvent(true);
4634
Prabir Pradhan678438e2023-04-13 19:32:51 +00004635 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4636 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4637 mDispatcher->notifyKey(keyDown);
4638 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004639
4640 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4641 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4642
4643 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004644 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004645
4646 window->consumeFocusEvent(false);
4647
Prabir Pradhan678438e2023-04-13 19:32:51 +00004648 mDispatcher->notifyKey(keyDown);
4649 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004650 window->assertNoEvents();
4651}
4652
Arthur Hung96483742022-11-15 03:30:48 +00004653TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4655 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4656 "Fake Window", ADISPLAY_ID_DEFAULT);
4657 // Ensure window is non-split and have some transform.
4658 window->setPreventSplitting(true);
4659 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004660 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004661
4662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004663 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004664 {50, 50}))
4665 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4666 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4667
4668 const MotionEvent secondFingerDownEvent =
4669 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4670 .displayId(ADISPLAY_ID_DEFAULT)
4671 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004672 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4673 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004674 .build();
4675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004676 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004677 InputEventInjectionSync::WAIT_FOR_RESULT))
4678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4679
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004680 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4681 ASSERT_NE(nullptr, event);
4682 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4683 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4684 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4685 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4686 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004687}
4688
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004689/**
4690 * Two windows: a splittable and a non-splittable.
4691 * The non-splittable window shouldn't receive any "incomplete" gestures.
4692 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4693 * The second pointer should be dropped because the initial window is splittable, so it won't get
4694 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4695 * "incomplete" gestures.
4696 */
4697TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4699 sp<FakeWindowHandle> leftWindow =
4700 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4701 ADISPLAY_ID_DEFAULT);
4702 leftWindow->setPreventSplitting(false);
4703 leftWindow->setFrame(Rect(0, 0, 100, 100));
4704 sp<FakeWindowHandle> rightWindow =
4705 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4706 ADISPLAY_ID_DEFAULT);
4707 rightWindow->setPreventSplitting(true);
4708 rightWindow->setFrame(Rect(100, 100, 200, 200));
4709 mDispatcher->onWindowInfosChanged(
4710 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4711
4712 // Touch down on left, splittable window
4713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4714 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4715 .build());
4716 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4717
4718 mDispatcher->notifyMotion(
4719 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4720 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4721 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4722 .build());
4723 leftWindow->assertNoEvents();
4724 rightWindow->assertNoEvents();
4725}
4726
Harry Cuttsb166c002023-05-09 13:06:05 +00004727TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4728 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4729 sp<FakeWindowHandle> window =
4730 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4731 window->setFrame(Rect(0, 0, 400, 400));
4732 sp<FakeWindowHandle> trustedOverlay =
4733 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4734 ADISPLAY_ID_DEFAULT);
4735 trustedOverlay->setSpy(true);
4736 trustedOverlay->setTrustedOverlay(true);
4737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004738 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004739
4740 // Start a three-finger touchpad swipe
4741 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4742 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4743 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4744 .build());
4745 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4746 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4747 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4748 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4749 .build());
4750 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4751 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4752 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4753 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4754 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4755 .build());
4756
4757 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4758 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4759 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4760
4761 // Move the swipe a bit
4762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4764 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4765 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4766 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4767 .build());
4768
4769 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4770
4771 // End the swipe
4772 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4773 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4774 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4775 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4776 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4777 .build());
4778 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4779 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4780 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4781 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4782 .build());
4783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4784 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4785 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4786 .build());
4787
4788 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4789 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4790 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4791
4792 window->assertNoEvents();
4793}
4794
4795TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4796 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4797 sp<FakeWindowHandle> window =
4798 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4799 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004801
4802 // Start a three-finger touchpad swipe
4803 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4804 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4805 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4806 .build());
4807 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4808 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4809 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4810 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4811 .build());
4812 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4813 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4814 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4815 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4816 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4817 .build());
4818
4819 // Move the swipe a bit
4820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, 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
4827 // End the swipe
4828 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4829 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4830 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4831 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4832 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4833 .build());
4834 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4835 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4836 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4837 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4838 .build());
4839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4840 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4841 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4842 .build());
4843
4844 window->assertNoEvents();
4845}
4846
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004847/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004848 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4849 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004850 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004851 */
4852TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4853 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4854 sp<FakeWindowHandle> window =
4855 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4856 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004857 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004858
4859 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4861 .downTime(baseTime + 10)
4862 .eventTime(baseTime + 10)
4863 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4864 .build());
4865
4866 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4867
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004868 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004869 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004870
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004872
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004873 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4874 .downTime(baseTime + 10)
4875 .eventTime(baseTime + 30)
4876 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4877 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4878 .build());
4879
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004880 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4881
4882 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004883 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4884 .downTime(baseTime + 10)
4885 .eventTime(baseTime + 40)
4886 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4887 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4888 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004889
4890 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4891
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4893 .downTime(baseTime + 10)
4894 .eventTime(baseTime + 50)
4895 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4896 .build());
4897
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004898 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4899
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4901 .downTime(baseTime + 60)
4902 .eventTime(baseTime + 60)
4903 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4904 .build());
4905
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004906 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004907}
4908
4909/**
Hu Guo771a7692023-09-17 20:51:08 +08004910 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4911 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4912 * its coordinates should be converted by the transform of the windows of target screen.
4913 */
4914TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4915 // This case will create a window and a spy window on the default display and mirror
4916 // window on the second display. cancel event is sent through spy window pilferPointers
4917 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4918
4919 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4920 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4921 spyWindowDefaultDisplay->setTrustedOverlay(true);
4922 spyWindowDefaultDisplay->setSpy(true);
4923
4924 sp<FakeWindowHandle> windowDefaultDisplay =
4925 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4926 ADISPLAY_ID_DEFAULT);
4927 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4928
4929 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4930 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4931
4932 // Add the windows to the dispatcher
4933 mDispatcher->onWindowInfosChanged(
4934 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4935 *windowSecondDisplay->getInfo()},
4936 {},
4937 0,
4938 0});
4939
4940 // Send down to ADISPLAY_ID_DEFAULT
4941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4942 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4943 {100, 100}))
4944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4945
4946 spyWindowDefaultDisplay->consumeMotionDown();
4947 windowDefaultDisplay->consumeMotionDown();
4948
4949 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4950
4951 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004952 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4953 ASSERT_NE(nullptr, event);
4954 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004955
4956 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4957 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4958 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4959 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004960 EXPECT_EQ(100, event->getX(0));
4961 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004962}
4963
4964/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004965 * Ensure the correct coordinate spaces are used by InputDispatcher.
4966 *
4967 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4968 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4969 * space.
4970 */
4971class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4972public:
4973 void SetUp() override {
4974 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004975 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004976 }
4977
4978 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4979 gui::DisplayInfo info;
4980 info.displayId = displayId;
4981 info.transform = transform;
4982 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004983 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004984 }
4985
4986 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4987 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004988 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004989 }
4990
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004991 void removeAllWindowsAndDisplays() {
4992 mDisplayInfos.clear();
4993 mWindowInfos.clear();
4994 }
4995
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004996 // Set up a test scenario where the display has a scaled projection and there are two windows
4997 // on the display.
4998 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4999 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5000 // respectively.
5001 ui::Transform displayTransform;
5002 displayTransform.set(2, 0, 0, 4);
5003 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5004
5005 std::shared_ptr<FakeApplicationHandle> application =
5006 std::make_shared<FakeApplicationHandle>();
5007
5008 // Add two windows to the display. Their frames are represented in the display space.
5009 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005010 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5011 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005012 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5013 addWindow(firstWindow);
5014
5015 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005016 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5017 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005018 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5019 addWindow(secondWindow);
5020 return {std::move(firstWindow), std::move(secondWindow)};
5021 }
5022
5023private:
5024 std::vector<gui::DisplayInfo> mDisplayInfos;
5025 std::vector<gui::WindowInfo> mWindowInfos;
5026};
5027
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005028TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005029 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5030 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005031 // selected so that if the hit test was performed with the point and the bounds being in
5032 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005033 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5034 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5035 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005036
5037 firstWindow->consumeMotionDown();
5038 secondWindow->assertNoEvents();
5039}
5040
5041// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5042// the event should be treated as being in the logical display space.
5043TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5044 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5045 // Send down to the first window. The point is represented in the logical display space. The
5046 // point is selected so that if the hit test was done in logical display space, then it would
5047 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005048 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005049 PointF{75 * 2, 55 * 4});
5050
5051 firstWindow->consumeMotionDown();
5052 secondWindow->assertNoEvents();
5053}
5054
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005055// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5056// event should be treated as being in the logical display space.
5057TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5058 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5059
5060 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5061 ui::Transform injectedEventTransform;
5062 injectedEventTransform.set(matrix);
5063 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5064 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5065
5066 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5067 .displayId(ADISPLAY_ID_DEFAULT)
5068 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005069 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005070 .x(untransformedPoint.x)
5071 .y(untransformedPoint.y))
5072 .build();
5073 event.transform(matrix);
5074
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005075 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005076 InputEventInjectionSync::WAIT_FOR_RESULT);
5077
5078 firstWindow->consumeMotionDown();
5079 secondWindow->assertNoEvents();
5080}
5081
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005082TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5083 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5084
5085 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005086 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5087 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5088 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005089
5090 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005091 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5092 ASSERT_NE(nullptr, event);
5093 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005094
5095 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005096 EXPECT_EQ(300, event->getRawX(0));
5097 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005098
5099 // Ensure that the x and y values are in the window's coordinate space.
5100 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5101 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005102 EXPECT_EQ(100, event->getX(0));
5103 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005104}
5105
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005106TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5107 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5108 // The monitor will always receive events in the logical display's coordinate space, because
5109 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00005110 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005111
5112 // Send down to the first window.
5113 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5114 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5115 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5116 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5117
5118 // Second pointer goes down on second window.
5119 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5120 ADISPLAY_ID_DEFAULT,
5121 {PointF{50, 100}, PointF{150, 220}}));
5122 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5123 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5124 {1, PointF{300, 880}}};
5125 monitor.consumeMotionEvent(
5126 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5127
5128 mDispatcher->cancelCurrentTouch();
5129
5130 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5131 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5132 monitor.consumeMotionEvent(
5133 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5134}
5135
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005136TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5137 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5138
5139 // Send down to the first window.
5140 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5141 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
5142 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5143
5144 // The pointer is transferred to the second window, and the second window receives it in the
5145 // correct coordinate space.
5146 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5147 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5148 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5149}
5150
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005151TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5152 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5153
5154 // Send hover move to the second window, and ensure it shows up as hover enter.
5155 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5156 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5157 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5158 WithCoords(100, 80), WithRawCoords(300, 880)));
5159
5160 // Touch down at the same location and ensure a hover exit is synthesized.
5161 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5162 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5163 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5164 WithRawCoords(300, 880)));
5165 secondWindow->consumeMotionEvent(
5166 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5167 secondWindow->assertNoEvents();
5168 firstWindow->assertNoEvents();
5169}
5170
Prabir Pradhan453ae732023-10-13 14:30:14 +00005171// Same as above, but while the window is being mirrored.
5172TEST_F(InputDispatcherDisplayProjectionTest,
5173 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5174 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5175
5176 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5177 ui::Transform secondDisplayTransform;
5178 secondDisplayTransform.set(matrix);
5179 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5180
5181 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5182 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5183 addWindow(secondWindowClone);
5184
5185 // Send hover move to the second window, and ensure it shows up as hover enter.
5186 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
5187 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5188 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5189 WithCoords(100, 80), WithRawCoords(300, 880)));
5190
5191 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5192 // display.
5193 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
5194 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5195 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5196 WithRawCoords(300, 880)));
5197 secondWindow->consumeMotionEvent(
5198 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5199 secondWindow->assertNoEvents();
5200 firstWindow->assertNoEvents();
5201}
5202
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005203TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5204 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5205
5206 // Send hover enter to second window
5207 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5208 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5209 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5210 WithCoords(100, 80), WithRawCoords(300, 880)));
5211
5212 mDispatcher->cancelCurrentTouch();
5213
5214 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5215 WithRawCoords(300, 880)));
5216 secondWindow->assertNoEvents();
5217 firstWindow->assertNoEvents();
5218}
5219
Prabir Pradhan453ae732023-10-13 14:30:14 +00005220// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005221TEST_F(InputDispatcherDisplayProjectionTest,
5222 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5223 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5224
5225 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5226 ui::Transform secondDisplayTransform;
5227 secondDisplayTransform.set(matrix);
5228 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5229
5230 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5231 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5232 addWindow(secondWindowClone);
5233
5234 // Send hover enter to second window
5235 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
5236 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
5237 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5238 WithCoords(100, 80), WithRawCoords(300, 880),
5239 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5240
5241 mDispatcher->cancelCurrentTouch();
5242
5243 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5244 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5245 WithRawCoords(300, 880),
5246 WithDisplayId(ADISPLAY_ID_DEFAULT)));
5247 secondWindow->assertNoEvents();
5248 firstWindow->assertNoEvents();
5249}
5250
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005251/** Ensure consistent behavior of InputDispatcher in all orientations. */
5252class InputDispatcherDisplayOrientationFixture
5253 : public InputDispatcherDisplayProjectionTest,
5254 public ::testing::WithParamInterface<ui::Rotation> {};
5255
5256// This test verifies the touchable region of a window for all rotations of the display by tapping
5257// in different locations on the display, specifically points close to the four corners of a
5258// window.
5259TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5260 constexpr static int32_t displayWidth = 400;
5261 constexpr static int32_t displayHeight = 800;
5262
5263 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5264
5265 const auto rotation = GetParam();
5266
5267 // Set up the display with the specified rotation.
5268 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5269 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5270 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5271 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5272 logicalDisplayWidth, logicalDisplayHeight);
5273 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
5274
5275 // Create a window with its bounds determined in the logical display.
5276 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5277 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
5278 sp<FakeWindowHandle> window =
5279 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
5280 window->setFrame(frameInDisplay, displayTransform);
5281 addWindow(window);
5282
5283 // The following points in logical display space should be inside the window.
5284 static const std::array<vec2, 4> insidePoints{
5285 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5286 for (const auto pointInsideWindow : insidePoints) {
5287 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5288 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005289 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5290 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5291 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005292 window->consumeMotionDown();
5293
Prabir Pradhan678438e2023-04-13 19:32:51 +00005294 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5295 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5296 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005297 window->consumeMotionUp();
5298 }
5299
5300 // The following points in logical display space should be outside the window.
5301 static const std::array<vec2, 5> outsidePoints{
5302 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5303 for (const auto pointOutsideWindow : outsidePoints) {
5304 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5305 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00005306 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5307 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5308 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005309
Prabir Pradhan678438e2023-04-13 19:32:51 +00005310 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
5311 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5312 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005313 }
5314 window->assertNoEvents();
5315}
5316
5317// Run the precision tests for all rotations.
5318INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
5319 InputDispatcherDisplayOrientationFixture,
5320 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
5321 ui::ROTATION_270),
5322 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
5323 return ftl::enum_string(testParamInfo.param);
5324 });
5325
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005326using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
5327 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005328
5329class TransferTouchFixture : public InputDispatcherTest,
5330 public ::testing::WithParamInterface<TransferFunction> {};
5331
5332TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07005333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005334
5335 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005336 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005337 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5338 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005339 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005340 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005341 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5342 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005343 sp<FakeWindowHandle> wallpaper =
5344 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
5345 wallpaper->setIsWallpaper(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005346 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005347 mDispatcher->onWindowInfosChanged(
5348 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005349
5350 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005351 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5352 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005353
Svet Ganov5d3bc372020-01-26 23:11:07 -08005354 // Only the first window should get the down event
5355 firstWindow->consumeMotionDown();
5356 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005357 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005358
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005359 // Transfer touch to the second window
5360 TransferFunction f = GetParam();
5361 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5362 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005363 // The first window gets cancel and the second gets down
5364 firstWindow->consumeMotionCancel();
5365 secondWindow->consumeMotionDown();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005366 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005367
5368 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005369 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5370 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005371 // The first window gets no events and the second gets up
5372 firstWindow->assertNoEvents();
5373 secondWindow->consumeMotionUp();
Arthur Hungc539dbb2022-12-08 07:45:36 +00005374 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005375}
5376
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005377/**
5378 * When 'transferTouch' API is invoked, dispatcher needs to find the "best" window to take touch
5379 * from. When we have spy windows, there are several windows to choose from: either spy, or the
5380 * 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
5381 * natural to the user.
5382 * In this test, we are sending a pointer to both spy window and first window. We then try to
5383 * transfer touch to the second window. The dispatcher should identify the first window as the
5384 * one that should lose the gesture, and therefore the action should be to move the gesture from
5385 * the first window to the second.
5386 * The main goal here is to test the behaviour of 'transferTouch' API, but it's still valid to test
5387 * the other API, as well.
5388 */
5389TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5391
5392 // Create a couple of windows + a spy window
5393 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005394 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005395 spyWindow->setTrustedOverlay(true);
5396 spyWindow->setSpy(true);
5397 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005399 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005400 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005401
5402 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005403 mDispatcher->onWindowInfosChanged(
5404 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005405
5406 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5408 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005409 // Only the first window and spy should get the down event
5410 spyWindow->consumeMotionDown();
5411 firstWindow->consumeMotionDown();
5412
5413 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
5414 // if f === 'transferTouch'.
5415 TransferFunction f = GetParam();
5416 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5417 ASSERT_TRUE(success);
5418 // The first window gets cancel and the second gets down
5419 firstWindow->consumeMotionCancel();
5420 secondWindow->consumeMotionDown();
5421
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));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005425 // The first window gets no events and the second+spy get up
5426 firstWindow->assertNoEvents();
5427 spyWindow->consumeMotionUp();
5428 secondWindow->consumeMotionUp();
5429}
5430
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005431TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005433
5434 PointF touchPoint = {10, 10};
5435
5436 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005437 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005438 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5439 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005440 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005441 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005442 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5443 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005444 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005445
5446 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005447 mDispatcher->onWindowInfosChanged(
5448 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005449
5450 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5453 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005454 // Only the first window should get the down event
5455 firstWindow->consumeMotionDown();
5456 secondWindow->assertNoEvents();
5457
5458 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005459 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5460 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005461 // Only the first window should get the pointer down event
5462 firstWindow->consumeMotionPointerDown(1);
5463 secondWindow->assertNoEvents();
5464
5465 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005466 TransferFunction f = GetParam();
5467 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5468 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005469 // The first window gets cancel and the second gets down and pointer down
5470 firstWindow->consumeMotionCancel();
5471 secondWindow->consumeMotionDown();
5472 secondWindow->consumeMotionPointerDown(1);
5473
5474 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005475 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5476 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005477 // The first window gets nothing and the second gets pointer up
5478 firstWindow->assertNoEvents();
5479 secondWindow->consumeMotionPointerUp(1);
5480
5481 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005482 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5483 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005484 // The first window gets nothing and the second gets up
5485 firstWindow->assertNoEvents();
5486 secondWindow->consumeMotionUp();
5487}
5488
Arthur Hungc539dbb2022-12-08 07:45:36 +00005489TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5490 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5491
5492 // Create a couple of windows
5493 sp<FakeWindowHandle> firstWindow =
5494 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5495 ADISPLAY_ID_DEFAULT);
5496 firstWindow->setDupTouchToWallpaper(true);
5497 sp<FakeWindowHandle> secondWindow =
5498 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5499 ADISPLAY_ID_DEFAULT);
5500 secondWindow->setDupTouchToWallpaper(true);
5501
5502 sp<FakeWindowHandle> wallpaper1 =
5503 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5504 wallpaper1->setIsWallpaper(true);
5505
5506 sp<FakeWindowHandle> wallpaper2 =
5507 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5508 wallpaper2->setIsWallpaper(true);
5509 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005510 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5511 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5512 {},
5513 0,
5514 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005515
5516 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005517 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5518 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005519
5520 // Only the first window should get the down event
5521 firstWindow->consumeMotionDown();
5522 secondWindow->assertNoEvents();
5523 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5524 wallpaper2->assertNoEvents();
5525
5526 // Transfer touch focus to the second window
5527 TransferFunction f = GetParam();
5528 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5529 ASSERT_TRUE(success);
5530
5531 // The first window gets cancel and the second gets down
5532 firstWindow->consumeMotionCancel();
5533 secondWindow->consumeMotionDown();
5534 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5535 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5536
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));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005540 // The first window gets no events and the second gets up
5541 firstWindow->assertNoEvents();
5542 secondWindow->consumeMotionUp();
5543 wallpaper1->assertNoEvents();
5544 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5545}
5546
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005547// For the cases of single pointer touch and two pointers non-split touch, the api's
5548// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
5549// for the case where there are multiple pointers split across several windows.
5550INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
5551 ::testing::Values(
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005552 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5553 sp<IBinder> /*ignored*/, sp<IBinder> destChannelToken) {
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005554 return dispatcher->transferTouch(destChannelToken,
5555 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005556 },
Siarhei Vishniakou18050092021-09-01 13:32:49 -07005557 [&](const std::unique_ptr<InputDispatcher>& dispatcher,
5558 sp<IBinder> from, sp<IBinder> to) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005559 return dispatcher->transferTouchFocus(from, to,
Harry Cutts33476232023-01-30 19:57:29 +00005560 /*isDragAndDrop=*/false);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005561 }));
5562
Svet Ganov5d3bc372020-01-26 23:11:07 -08005563TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005564 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005565
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005566 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005567 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5568 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005569 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005570
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005571 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005572 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5573 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005574 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005575
5576 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005577 mDispatcher->onWindowInfosChanged(
5578 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005579
5580 PointF pointInFirst = {300, 200};
5581 PointF pointInSecond = {300, 600};
5582
5583 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005584 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5585 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5586 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005587 // Only the first window should get the down event
5588 firstWindow->consumeMotionDown();
5589 secondWindow->assertNoEvents();
5590
5591 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005592 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5593 ADISPLAY_ID_DEFAULT,
5594 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005595 // The first window gets a move and the second a down
5596 firstWindow->consumeMotionMove();
5597 secondWindow->consumeMotionDown();
5598
5599 // Transfer touch focus to the second window
5600 mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
5601 // The first window gets cancel and the new gets pointer down (it already saw down)
5602 firstWindow->consumeMotionCancel();
5603 secondWindow->consumeMotionPointerDown(1);
5604
5605 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005606 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5607 ADISPLAY_ID_DEFAULT,
5608 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005609 // The first window gets nothing and the second gets pointer up
5610 firstWindow->assertNoEvents();
5611 secondWindow->consumeMotionPointerUp(1);
5612
5613 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005614 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5615 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005616 // The first window gets nothing and the second gets up
5617 firstWindow->assertNoEvents();
5618 secondWindow->consumeMotionUp();
5619}
5620
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005621// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
5622// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
5623// touch is not supported, so the touch should continue on those windows and the transferred-to
5624// window should get nothing.
5625TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
5626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5627
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005628 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005629 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5630 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005631 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005632
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005633 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005634 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5635 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005636 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005637
5638 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005639 mDispatcher->onWindowInfosChanged(
5640 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005641
5642 PointF pointInFirst = {300, 200};
5643 PointF pointInSecond = {300, 600};
5644
5645 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005646 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5647 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5648 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005649 // Only the first window should get the down event
5650 firstWindow->consumeMotionDown();
5651 secondWindow->assertNoEvents();
5652
5653 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005654 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5655 ADISPLAY_ID_DEFAULT,
5656 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005657 // The first window gets a move and the second a down
5658 firstWindow->consumeMotionMove();
5659 secondWindow->consumeMotionDown();
5660
5661 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005662 const bool transferred =
5663 mDispatcher->transferTouch(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005664 // The 'transferTouch' call should not succeed, because there are 2 touched windows
5665 ASSERT_FALSE(transferred);
5666 firstWindow->assertNoEvents();
5667 secondWindow->assertNoEvents();
5668
5669 // The rest of the dispatch should proceed as normal
5670 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005671 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5672 ADISPLAY_ID_DEFAULT,
5673 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005674 // The first window gets MOVE and the second gets pointer up
5675 firstWindow->consumeMotionMove();
5676 secondWindow->consumeMotionUp();
5677
5678 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005679 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5680 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005681 // The first window gets nothing and the second gets up
5682 firstWindow->consumeMotionUp();
5683 secondWindow->assertNoEvents();
5684}
5685
Arthur Hungabbb9d82021-09-01 14:52:30 +00005686// This case will create two windows and one mirrored window on the default display and mirror
5687// two windows on the second display. It will test if 'transferTouchFocus' works fine if we put
5688// the windows info of second display before default display.
5689TEST_F(InputDispatcherTest, TransferTouchFocus_CloneSurface) {
5690 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5691 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005692 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005693 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005694 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005695 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005696 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005697
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005698 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005699 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005700
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005701 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005702 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005703
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005704 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005705 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005706
5707 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005708 mDispatcher->onWindowInfosChanged(
5709 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5710 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5711 *secondWindowInPrimary->getInfo()},
5712 {},
5713 0,
5714 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005715
5716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005718 {50, 50}))
5719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5720
5721 // Window should receive motion event.
5722 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5723
5724 // Transfer touch focus
5725 ASSERT_TRUE(mDispatcher->transferTouchFocus(firstWindowInPrimary->getToken(),
5726 secondWindowInPrimary->getToken()));
5727 // The first window gets cancel.
5728 firstWindowInPrimary->consumeMotionCancel();
5729 secondWindowInPrimary->consumeMotionDown();
5730
5731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005732 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005733 ADISPLAY_ID_DEFAULT, {150, 50}))
5734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5735 firstWindowInPrimary->assertNoEvents();
5736 secondWindowInPrimary->consumeMotionMove();
5737
5738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005739 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005740 {150, 50}))
5741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5742 firstWindowInPrimary->assertNoEvents();
5743 secondWindowInPrimary->consumeMotionUp();
5744}
5745
5746// Same as TransferTouchFocus_CloneSurface, but this touch on the secondary display and use
5747// 'transferTouch' api.
5748TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
5749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5750 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005751 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005752 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005753 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005754 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005755 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005756
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005757 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005758 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005759
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005760 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005761 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005762
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005763 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005764 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005765
5766 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005767 mDispatcher->onWindowInfosChanged(
5768 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5769 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5770 *secondWindowInPrimary->getInfo()},
5771 {},
5772 0,
5773 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005774
5775 // Touch on second display.
5776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005777 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5778 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005779 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5780
5781 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005782 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005783
5784 // Transfer touch focus
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005785 ASSERT_TRUE(mDispatcher->transferTouch(secondWindowInSecondary->getToken(), SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005786
5787 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005788 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
5789 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005790
5791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005792 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005793 SECOND_DISPLAY_ID, {150, 50}))
5794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005795 firstWindowInSecondary->assertNoEvents();
5796 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005797
5798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005799 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005801 firstWindowInSecondary->assertNoEvents();
5802 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005803}
5804
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005805TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005807 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5808 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005809
Vishnu Nair47074b82020-08-14 11:54:47 -07005810 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005812 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005813
5814 window->consumeFocusEvent(true);
5815
Prabir Pradhan678438e2023-04-13 19:32:51 +00005816 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005817
5818 // Window should receive key down event.
5819 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005820
5821 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005822 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005823 mFakePolicy->assertUserActivityPoked();
5824}
5825
5826TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5828 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5829 "Fake Window", ADISPLAY_ID_DEFAULT);
5830
5831 window->setDisableUserActivity(true);
5832 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005834 setFocusedWindow(window);
5835
5836 window->consumeFocusEvent(true);
5837
5838 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5839
5840 // Window should receive key down event.
5841 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5842
5843 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005844 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005845 mFakePolicy->assertUserActivityNotPoked();
5846}
5847
5848TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5849 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5850 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5851 "Fake Window", ADISPLAY_ID_DEFAULT);
5852
5853 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005854 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005855 setFocusedWindow(window);
5856
5857 window->consumeFocusEvent(true);
5858
5859 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5860 mDispatcher->waitForIdle();
5861
5862 // System key is not passed down
5863 window->assertNoEvents();
5864
5865 // Should have poked user activity
5866 mFakePolicy->assertUserActivityPoked();
5867}
5868
5869TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5871 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5872 "Fake Window", ADISPLAY_ID_DEFAULT);
5873
5874 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005875 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005876 setFocusedWindow(window);
5877
5878 window->consumeFocusEvent(true);
5879
5880 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5881 mDispatcher->waitForIdle();
5882
5883 // System key is not passed down
5884 window->assertNoEvents();
5885
5886 // Should have poked user activity
5887 mFakePolicy->assertUserActivityPoked();
5888}
5889
5890TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5892 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5893 "Fake Window", ADISPLAY_ID_DEFAULT);
5894
5895 window->setDisableUserActivity(true);
5896 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005897 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005898 setFocusedWindow(window);
5899
5900 window->consumeFocusEvent(true);
5901
5902 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5903 mDispatcher->waitForIdle();
5904
5905 // System key is not passed down
5906 window->assertNoEvents();
5907
5908 // Should have poked user activity
5909 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005910}
5911
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005912TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5913 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5914 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5915 "Fake Window", ADISPLAY_ID_DEFAULT);
5916
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005917 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005918
5919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005920 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005921 ADISPLAY_ID_DEFAULT, {100, 100}))
5922 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5923
5924 window->consumeMotionEvent(
5925 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5926
5927 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005928 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005929 mFakePolicy->assertUserActivityPoked();
5930}
5931
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005932TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005934 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5935 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005936
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005937 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005938
Prabir Pradhan678438e2023-04-13 19:32:51 +00005939 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005940 mDispatcher->waitForIdle();
5941
5942 window->assertNoEvents();
5943}
5944
5945// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5946TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5949 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005950
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005951 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005952
5953 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005954 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005955 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005956 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5957 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005958
5959 // Window should receive only the motion event
5960 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5961 window->assertNoEvents(); // Key event or focus event will not be received
5962}
5963
arthurhungea3f4fc2020-12-21 23:18:53 +08005964TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5966
arthurhungea3f4fc2020-12-21 23:18:53 +08005967 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005968 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5969 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005970 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005971
arthurhungea3f4fc2020-12-21 23:18:53 +08005972 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005973 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5974 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005975 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005976
5977 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005978 mDispatcher->onWindowInfosChanged(
5979 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005980
5981 PointF pointInFirst = {300, 200};
5982 PointF pointInSecond = {300, 600};
5983
5984 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5986 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5987 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005988 // Only the first window should get the down event
5989 firstWindow->consumeMotionDown();
5990 secondWindow->assertNoEvents();
5991
5992 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005993 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5994 ADISPLAY_ID_DEFAULT,
5995 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005996 // The first window gets a move and the second a down
5997 firstWindow->consumeMotionMove();
5998 secondWindow->consumeMotionDown();
5999
6000 // Send pointer cancel to the second window
6001 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08006002 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08006003 {pointInFirst, pointInSecond});
6004 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006005 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006006 // The first window gets move and the second gets cancel.
6007 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6008 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6009
6010 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006011 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6012 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006013 // The first window gets up and the second gets nothing.
6014 firstWindow->consumeMotionUp();
6015 secondWindow->assertNoEvents();
6016}
6017
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006018TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6020
6021 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006022 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006023 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006024 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6025 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6026 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6027
Harry Cutts33476232023-01-30 19:57:29 +00006028 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006029 window->assertNoEvents();
6030 mDispatcher->waitForIdle();
6031}
6032
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006033using InputDispatcherMonitorTest = InputDispatcherTest;
6034
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006035/**
6036 * Two entities that receive touch: A window, and a global monitor.
6037 * The touch goes to the window, and then the window disappears.
6038 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6039 * for the monitor, as well.
6040 * 1. foregroundWindow
6041 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6042 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006043TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6045 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006046 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006047
Prabir Pradhanfb549072023-10-05 19:17:36 +00006048 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006049
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006050 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006052 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006053 {100, 200}))
6054 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6055
6056 // Both the foreground window and the global monitor should receive the touch down
6057 window->consumeMotionDown();
6058 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
6059
6060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006061 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006062 ADISPLAY_ID_DEFAULT, {110, 200}))
6063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6064
6065 window->consumeMotionMove();
6066 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6067
6068 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006069 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006070 window->consumeMotionCancel();
6071 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6072
6073 // If more events come in, there will be no more foreground window to send them to. This will
6074 // cause a cancel for the monitor, as well.
6075 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006076 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006077 ADISPLAY_ID_DEFAULT, {120, 200}))
6078 << "Injection should fail because the window was removed";
6079 window->assertNoEvents();
6080 // Global monitor now gets the cancel
6081 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
6082}
6083
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006084TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006086 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6087 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006088 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006089
Prabir Pradhanfb549072023-10-05 19:17:36 +00006090 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006091
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006093 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00006095 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08006096 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006097}
6098
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006099TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00006100 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006101
Chris Yea209fde2020-07-22 13:54:51 -07006102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006103 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6104 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006105 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006106
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006108 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08006110 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006111 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006112
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006113 // Pilfer pointers from the monitor.
6114 // This should not do anything and the window should continue to receive events.
6115 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006116
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006118 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006119 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006121
6122 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
6123 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006124}
6125
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006126TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006127 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006128 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6129 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006130 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006131 window->setWindowOffset(20, 40);
6132 window->setWindowTransform(0, 1, -1, 0);
6133
Prabir Pradhanfb549072023-10-05 19:17:36 +00006134 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006135
6136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006137 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006138 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6139 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006140 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6141 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006142 // Even though window has transform, gesture monitor must not.
6143 ASSERT_EQ(ui::Transform(), event->getTransform());
6144}
6145
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006146TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006147 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00006148 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006149
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006150 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006152 << "Injection should fail if there is a monitor, but no touchable window";
6153 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006154}
6155
Linnan Lid8150952024-01-26 18:07:17 +00006156/**
6157 * Two displays
6158 * The first monitor has a foreground window, a monitor
6159 * The second window has only one monitor.
6160 * We first inject a Down event into the first display, this injection should succeed and both
6161 * the foreground window and monitor should receive a down event, then inject a Down event into
6162 * the second display as well, this injection should fail, at this point, the first display
6163 * window and monitor should not receive a cancel or any other event.
6164 * Continue to inject Move and UP events to the first display, the events should be received
6165 * normally by the foreground window and monitor.
6166 */
6167TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6168 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6169 sp<FakeWindowHandle> window =
6170 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6171
6172 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6173 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6174
6175 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6176 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6177 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6178 {100, 200}))
6179 << "The down event injected into the first display should succeed";
6180
6181 window->consumeMotionDown();
6182 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006183
6184 ASSERT_EQ(InputEventInjectionResult::FAILED,
6185 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6186 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006187 << "The down event injected into the second display should fail since there's no "
6188 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006189
6190 // Continue to inject event to first display.
6191 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6192 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6193 ADISPLAY_ID_DEFAULT, {110, 220}))
6194 << "The move event injected into the first display should succeed";
6195
6196 window->consumeMotionMove();
6197 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006198
6199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6200 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6201 {110, 220}))
6202 << "The up event injected into the first display should succeed";
6203
6204 window->consumeMotionUp();
6205 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006206
6207 window->assertNoEvents();
6208 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006209 secondMonitor.assertNoEvents();
6210}
6211
6212/**
6213 * Two displays
6214 * There is a monitor and foreground window on each display.
6215 * First, we inject down events into each of the two displays, at this point, the foreground windows
6216 * and monitors on both displays should receive down events.
6217 * At this point, the foreground window of the second display goes away, the gone window should
6218 * receive the cancel event, and the other windows and monitors should not receive any events.
6219 * Inject a move event into the second display. At this point, the injection should fail because
6220 * the second display no longer has a foreground window. At this point, the monitor on the second
6221 * display should receive a cancel event, and any windows or monitors on the first display should
6222 * not receive any events, and any subsequent injection of events into the second display should
6223 * also fail.
6224 * Continue to inject events into the first display, and the events should all be injected
6225 * successfully and received normally.
6226 */
6227TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
6228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6229 sp<FakeWindowHandle> window =
6230 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6231 sp<FakeWindowHandle> secondWindow =
6232 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
6233 SECOND_DISPLAY_ID);
6234
6235 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6236 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6237
6238 // There is a foreground window on both displays.
6239 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
6240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6242 {100, 200}))
6243 << "The down event injected into the first display should succeed";
6244
6245 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6246 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006247
6248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6249 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6250 {100, 200}))
6251 << "The down event injected into the second display should succeed";
6252
Linnan Lid8150952024-01-26 18:07:17 +00006253 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
6254 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
6255
6256 // Now second window is gone away.
6257 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6258
6259 // The gone window should receive a cancel, and the monitor on the second display should not
6260 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00006261 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
6262 secondMonitor.assertNoEvents();
6263
6264 ASSERT_EQ(InputEventInjectionResult::FAILED,
6265 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6266 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006267 << "The move event injected into the second display should fail because there's no "
6268 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006269 // Now the monitor on the second display should receive a cancel event.
6270 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00006271
6272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6273 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6274 ADISPLAY_ID_DEFAULT, {110, 200}))
6275 << "The move event injected into the first display should succeed";
6276
6277 window->consumeMotionMove();
6278 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006279
6280 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006281 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6282 {110, 220}))
6283 << "The up event injected into the second display should fail because there's no "
6284 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006285
6286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6287 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6288 {110, 220}))
6289 << "The up event injected into the first display should succeed";
6290
6291 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
6292 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006293
Linnan Lid8150952024-01-26 18:07:17 +00006294 window->assertNoEvents();
6295 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006296 secondWindow->assertNoEvents();
6297 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00006298}
6299
6300/**
6301 * One display with transform
6302 * There is a foreground window and a monitor on the display
6303 * Inject down event and move event sequentially, the foreground window and monitor can receive down
6304 * event and move event, then let the foreground window go away, the foreground window receives
6305 * cancel event, inject move event again, the monitor receives cancel event, all the events received
6306 * by the monitor should be with the same transform as the display
6307 */
6308TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
6309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6310 sp<FakeWindowHandle> window =
6311 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
6312 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
6313
6314 ui::Transform transform;
6315 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6316
6317 gui::DisplayInfo displayInfo;
6318 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6319 displayInfo.transform = transform;
6320
6321 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
6322
6323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6324 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6325 {100, 200}))
6326 << "The down event injected should succeed";
6327
6328 window->consumeMotionDown();
6329 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
6330 EXPECT_EQ(transform, downMotionEvent->getTransform());
6331 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
6332
6333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6334 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6335 ADISPLAY_ID_DEFAULT, {110, 220}))
6336 << "The move event injected should succeed";
6337
6338 window->consumeMotionMove();
6339 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
6340 EXPECT_EQ(transform, moveMotionEvent->getTransform());
6341 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
6342
6343 // Let foreground window gone
6344 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
6345
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006346 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00006347 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00006348
6349 ASSERT_EQ(InputEventInjectionResult::FAILED,
6350 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6351 ADISPLAY_ID_DEFAULT, {110, 220}))
6352 << "The move event injected should failed";
6353 // Now foreground should not receive any events, but monitor should receive a cancel event
6354 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006355 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6356 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6357 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6358 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6359
6360 // Other event inject to this display should fail.
6361 ASSERT_EQ(InputEventInjectionResult::FAILED,
6362 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6363 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006364 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006365 window->assertNoEvents();
6366 monitor.assertNoEvents();
6367}
6368
chaviw81e2bb92019-12-18 15:03:51 -08006369TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6372 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006373
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006374 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006375
6376 NotifyMotionArgs motionArgs =
6377 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6378 ADISPLAY_ID_DEFAULT);
6379
Prabir Pradhan678438e2023-04-13 19:32:51 +00006380 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006381 // Window should receive motion down event.
6382 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6383
6384 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006385 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006386 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6387 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6388 motionArgs.pointerCoords[0].getX() - 10);
6389
Prabir Pradhan678438e2023-04-13 19:32:51 +00006390 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006391 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006392}
6393
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006394/**
6395 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6396 * the device default right away. In the test scenario, we check both the default value,
6397 * and the action of enabling / disabling.
6398 */
6399TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006401 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6402 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006403 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006404
6405 // Set focused application.
6406 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006407 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006408
6409 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006410 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006411 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006412 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006413
6414 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006415 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006416 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006417 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006418
6419 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006420 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006421 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006422 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006423 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006424 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006425 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006426 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006427
6428 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006429 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006430 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006431 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006432
6433 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006434 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006435 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006436 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006437 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006438 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006439 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006440 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006441
6442 window->assertNoEvents();
6443}
6444
Gang Wange9087892020-01-07 12:17:14 -05006445TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006447 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6448 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006449
6450 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006451 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006452
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006454 setFocusedWindow(window);
6455
Harry Cutts33476232023-01-30 19:57:29 +00006456 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006457
Prabir Pradhan678438e2023-04-13 19:32:51 +00006458 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6459 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006460
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006461 std::unique_ptr<KeyEvent> event = window->consumeKey();
6462 ASSERT_NE(event, nullptr);
6463 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006464 ASSERT_NE(verified, nullptr);
6465 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6466
6467 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6468 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6469 ASSERT_EQ(keyArgs.source, verified->source);
6470 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6471
6472 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6473
6474 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006475 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006476 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006477 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6478 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6479 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6480 ASSERT_EQ(0, verifiedKey.repeatCount);
6481}
6482
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006483TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6486 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006487
6488 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6489
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006490 ui::Transform transform;
6491 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6492
6493 gui::DisplayInfo displayInfo;
6494 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6495 displayInfo.transform = transform;
6496
Patrick Williamsd828f302023-04-28 17:52:08 -05006497 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006498
Prabir Pradhan678438e2023-04-13 19:32:51 +00006499 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006500 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6501 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006502 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006503
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006504 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6505 ASSERT_NE(nullptr, event);
6506 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006507 ASSERT_NE(verified, nullptr);
6508 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6509
6510 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6511 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6512 EXPECT_EQ(motionArgs.source, verified->source);
6513 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6514
6515 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6516
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006517 const vec2 rawXY =
6518 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6519 motionArgs.pointerCoords[0].getXYValue());
6520 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6521 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006522 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006523 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006524 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006525 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6526 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6527}
6528
chaviw09c8d2d2020-08-24 15:48:26 -07006529/**
6530 * Ensure that separate calls to sign the same data are generating the same key.
6531 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6532 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6533 * tests.
6534 */
6535TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6536 KeyEvent event = getTestKeyEvent();
6537 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6538
6539 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6540 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6541 ASSERT_EQ(hmac1, hmac2);
6542}
6543
6544/**
6545 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6546 */
6547TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6548 KeyEvent event = getTestKeyEvent();
6549 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6550 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6551
6552 verifiedEvent.deviceId += 1;
6553 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6554
6555 verifiedEvent.source += 1;
6556 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6557
6558 verifiedEvent.eventTimeNanos += 1;
6559 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6560
6561 verifiedEvent.displayId += 1;
6562 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6563
6564 verifiedEvent.action += 1;
6565 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6566
6567 verifiedEvent.downTimeNanos += 1;
6568 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6569
6570 verifiedEvent.flags += 1;
6571 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6572
6573 verifiedEvent.keyCode += 1;
6574 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6575
6576 verifiedEvent.scanCode += 1;
6577 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6578
6579 verifiedEvent.metaState += 1;
6580 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6581
6582 verifiedEvent.repeatCount += 1;
6583 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6584}
6585
Vishnu Nair958da932020-08-21 17:12:37 -07006586TEST_F(InputDispatcherTest, SetFocusedWindow) {
6587 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6588 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006589 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006590 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006591 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006592 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6593
6594 // Top window is also focusable but is not granted focus.
6595 windowTop->setFocusable(true);
6596 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006597 mDispatcher->onWindowInfosChanged(
6598 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006599 setFocusedWindow(windowSecond);
6600
6601 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006603 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006604
6605 // Focused window should receive event.
6606 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6607 windowTop->assertNoEvents();
6608}
6609
6610TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6611 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6612 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006613 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006614 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6615
6616 window->setFocusable(true);
6617 // Release channel for window is no longer valid.
6618 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006619 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006620 setFocusedWindow(window);
6621
6622 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006623 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006624
6625 // window channel is invalid, so it should not receive any input event.
6626 window->assertNoEvents();
6627}
6628
6629TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6630 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6631 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006632 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006633 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006634 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6635
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006636 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006637 setFocusedWindow(window);
6638
6639 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006640 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006641
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006642 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006643 window->assertNoEvents();
6644}
6645
6646TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6648 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006649 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006650 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006651 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006652 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6653
6654 windowTop->setFocusable(true);
6655 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006656 mDispatcher->onWindowInfosChanged(
6657 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006658 setFocusedWindow(windowTop);
6659 windowTop->consumeFocusEvent(true);
6660
Chavi Weingarten847e8512023-03-29 00:26:09 +00006661 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006662 mDispatcher->onWindowInfosChanged(
6663 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006664 windowSecond->consumeFocusEvent(true);
6665 windowTop->consumeFocusEvent(false);
6666
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006668 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006669
6670 // Focused window should receive event.
6671 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6672}
6673
Chavi Weingarten847e8512023-03-29 00:26:09 +00006674TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6676 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006677 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006678 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006679 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006680 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6681
6682 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006683 windowSecond->setFocusable(false);
6684 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006685 mDispatcher->onWindowInfosChanged(
6686 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006687 setFocusedWindow(windowTop);
6688 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006689
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006690 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006691 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006692
6693 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006694 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006695 windowSecond->assertNoEvents();
6696}
6697
6698TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6700 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006701 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006702 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006703 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6704 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006705 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6706
6707 window->setFocusable(true);
6708 previousFocusedWindow->setFocusable(true);
6709 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006710 mDispatcher->onWindowInfosChanged(
6711 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006712 setFocusedWindow(previousFocusedWindow);
6713 previousFocusedWindow->consumeFocusEvent(true);
6714
6715 // Requesting focus on invisible window takes focus from currently focused window.
6716 setFocusedWindow(window);
6717 previousFocusedWindow->consumeFocusEvent(false);
6718
6719 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006721 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6722 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006723
6724 // Window does not get focus event or key down.
6725 window->assertNoEvents();
6726
6727 // Window becomes visible.
6728 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006729 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006730
6731 // Window receives focus event.
6732 window->consumeFocusEvent(true);
6733 // Focused window receives key down.
6734 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6735}
6736
Vishnu Nair599f1412021-06-21 10:39:58 -07006737TEST_F(InputDispatcherTest, DisplayRemoved) {
6738 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6739 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006740 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006741 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6742
6743 // window is granted focus.
6744 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006745 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006746 setFocusedWindow(window);
6747 window->consumeFocusEvent(true);
6748
6749 // When a display is removed window loses focus.
6750 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6751 window->consumeFocusEvent(false);
6752}
6753
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006754/**
6755 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6756 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6757 * of the 'slipperyEnterWindow'.
6758 *
6759 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6760 * a way so that the touched location is no longer covered by the top window.
6761 *
6762 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6763 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6764 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6765 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6766 * with ACTION_DOWN).
6767 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6768 * window moved itself away from the touched location and had Flag::SLIPPERY.
6769 *
6770 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6771 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6772 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6773 *
6774 * In this test, we ensure that the event received by the bottom window has
6775 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6776 */
6777TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006778 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006779 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006780
6781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6782 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6783
6784 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006785 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006786 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006787 // Make sure this one overlaps the bottom window
6788 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6789 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6790 // one. Windows with the same owner are not considered to be occluding each other.
6791 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6792
6793 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006794 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006795 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6796
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006797 mDispatcher->onWindowInfosChanged(
6798 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006799
6800 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006801 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6802 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6803 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006804 slipperyExitWindow->consumeMotionDown();
6805 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006806 mDispatcher->onWindowInfosChanged(
6807 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006808
Prabir Pradhan678438e2023-04-13 19:32:51 +00006809 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6810 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6811 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006812
6813 slipperyExitWindow->consumeMotionCancel();
6814
6815 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6816 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6817}
6818
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006819/**
6820 * Two windows, one on the left and another on the right. The left window is slippery. The right
6821 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6822 * touch moves from the left window into the right window, the gesture should continue to go to the
6823 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6824 * reproduces a crash.
6825 */
6826TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6828
6829 sp<FakeWindowHandle> leftSlipperyWindow =
6830 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6831 leftSlipperyWindow->setSlippery(true);
6832 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6833
6834 sp<FakeWindowHandle> rightDropTouchesWindow =
6835 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6836 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6837 rightDropTouchesWindow->setDropInput(true);
6838
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006839 mDispatcher->onWindowInfosChanged(
6840 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006841
6842 // Start touch in the left window
6843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6844 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6845 .build());
6846 leftSlipperyWindow->consumeMotionDown();
6847
6848 // And move it into the right window
6849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6850 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6851 .build());
6852
6853 // Since the right window isn't eligible to receive input, touch does not slip.
6854 // The left window continues to receive the gesture.
6855 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6856 rightDropTouchesWindow->assertNoEvents();
6857}
6858
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006859/**
6860 * A single window is on screen first. Touch is injected into that window. Next, a second window
6861 * appears. Since the first window is slippery, touch will move from the first window to the second.
6862 */
6863TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6865 sp<FakeWindowHandle> originalWindow =
6866 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6867 originalWindow->setFrame(Rect(0, 0, 200, 200));
6868 originalWindow->setSlippery(true);
6869
6870 sp<FakeWindowHandle> appearingWindow =
6871 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6872 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6873
6874 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6875
6876 // Touch down on the original window
6877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6878 injectMotionEvent(*mDispatcher,
6879 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6880 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6881 .build()));
6882 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6883
6884 // Now, a new window appears. This could be, for example, a notification shade that appears
6885 // after user starts to drag down on the launcher window.
6886 mDispatcher->onWindowInfosChanged(
6887 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6889 injectMotionEvent(*mDispatcher,
6890 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6891 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6892 .build()));
6893 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6894 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6896 injectMotionEvent(*mDispatcher,
6897 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6898 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6899 .build()));
6900 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6901
6902 originalWindow->assertNoEvents();
6903 appearingWindow->assertNoEvents();
6904}
6905
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006906TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006907 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6909
6910 sp<FakeWindowHandle> leftWindow =
6911 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6912 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006913 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006914
6915 sp<FakeWindowHandle> rightSpy =
6916 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6917 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006918 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006919 rightSpy->setSpy(true);
6920 rightSpy->setTrustedOverlay(true);
6921
6922 sp<FakeWindowHandle> rightWindow =
6923 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6924 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006925 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006926
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006927 mDispatcher->onWindowInfosChanged(
6928 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006929
6930 // Touch in the left window
6931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6932 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6933 .build());
6934 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6935 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006936 ASSERT_NO_FATAL_FAILURE(
6937 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006938
6939 // Touch another finger over the right windows
6940 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6941 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6942 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6943 .build());
6944 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6945 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6946 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6947 mDispatcher->waitForIdle();
6948 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006949 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6950 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006951
6952 // Release finger over left window. The UP actions are not treated as device interaction.
6953 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6954 // is part of the UP action, we do not treat this as device interaction.
6955 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6956 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6957 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6958 .build());
6959 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6960 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6961 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6962 mDispatcher->waitForIdle();
6963 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6964
6965 // Move remaining finger
6966 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6967 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6968 .build());
6969 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6970 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6971 mDispatcher->waitForIdle();
6972 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006973 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006974
6975 // Release all fingers
6976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6977 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6978 .build());
6979 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6980 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6981 mDispatcher->waitForIdle();
6982 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6983}
6984
6985TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6987
6988 sp<FakeWindowHandle> window =
6989 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6990 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006991 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006992
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006993 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006994 setFocusedWindow(window);
6995 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6996
6997 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6998 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6999 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007000 ASSERT_NO_FATAL_FAILURE(
7001 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007002
7003 // The UP actions are not treated as device interaction.
7004 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
7005 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
7006 mDispatcher->waitForIdle();
7007 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7008}
7009
Prabir Pradhan5893d362023-11-17 04:30:40 +00007010TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7011 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7012
7013 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
7014 ADISPLAY_ID_DEFAULT);
7015 left->setFrame(Rect(0, 0, 100, 100));
7016 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
7017 "Right Window", ADISPLAY_ID_DEFAULT);
7018 right->setFrame(Rect(100, 0, 200, 100));
7019 sp<FakeWindowHandle> spy =
7020 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
7021 spy->setFrame(Rect(0, 0, 200, 100));
7022 spy->setTrustedOverlay(true);
7023 spy->setSpy(true);
7024
7025 mDispatcher->onWindowInfosChanged(
7026 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
7027
7028 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
7029 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
7030 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
7031 mDispatcher->notifyMotion(notifyArgs);
7032
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007033 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007034 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
7035 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007036 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007037 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7038 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007039 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007040 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7041
7042 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
7043 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7044 {PointF{150, 50}});
7045 mDispatcher->notifyMotion(notifyArgs);
7046
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007047 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00007048 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
7049 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007050 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007051 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
7052 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007053 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00007054 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
7055
7056 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
7057}
7058
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007059class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
7060protected:
7061 std::shared_ptr<FakeApplicationHandle> mApp;
7062 sp<FakeWindowHandle> mWindow;
7063
7064 virtual void SetUp() override {
7065 InputDispatcherTest::SetUp();
7066
7067 mApp = std::make_shared<FakeApplicationHandle>();
7068
7069 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
7070 mWindow->setFrame(Rect(0, 0, 100, 100));
7071
7072 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7073 setFocusedWindow(mWindow);
7074 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
7075 }
7076
7077 void setFallback(int32_t keycode) {
7078 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
7079 return KeyEventBuilder(event).keyCode(keycode).build();
7080 });
7081 }
7082
7083 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007084 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
7085 ASSERT_NE(nullptr, event);
7086 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00007087 }
7088};
7089
7090TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
7091 mDispatcher->notifyKey(
7092 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7093 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7094 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7095}
7096
7097TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
7098 mDispatcher->notifyKey(
7099 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7100 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
7101 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7102}
7103
7104TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
7105 mDispatcher->notifyKey(
7106 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7107
7108 // Do not handle this key event.
7109 consumeKey(/*handled=*/false,
7110 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7111 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7112
7113 // Since the policy did not request any fallback to be generated, ensure there are no events.
7114 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7115}
7116
7117TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
7118 setFallback(AKEYCODE_B);
7119 mDispatcher->notifyKey(
7120 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7121
7122 // Do not handle this key event.
7123 consumeKey(/*handled=*/false,
7124 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7125
7126 // Since the key was not handled, ensure the fallback event was dispatched instead.
7127 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7128 consumeKey(/*handled=*/true,
7129 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7130 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7131
7132 // Release the original key, and ensure the fallback key is also released.
7133 mDispatcher->notifyKey(
7134 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7135 consumeKey(/*handled=*/false,
7136 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7137 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7138 consumeKey(/*handled=*/true,
7139 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7140 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7141
7142 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7143 mWindow->assertNoEvents();
7144}
7145
7146TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
7147 setFallback(AKEYCODE_B);
7148 mDispatcher->notifyKey(
7149 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7150
7151 // Do not handle this key event, but handle the fallback.
7152 consumeKey(/*handled=*/false,
7153 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7154 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7155 consumeKey(/*handled=*/true,
7156 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7157 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7158
7159 // Release the original key, and ensure the fallback key is also released.
7160 mDispatcher->notifyKey(
7161 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7162 // But this time, the app handles the original key.
7163 consumeKey(/*handled=*/true,
7164 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7165 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7166 // Ensure the fallback key is canceled.
7167 consumeKey(/*handled=*/true,
7168 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7169 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7170
7171 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7172 mWindow->assertNoEvents();
7173}
7174
7175TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
7176 setFallback(AKEYCODE_B);
7177 mDispatcher->notifyKey(
7178 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7179
7180 // Do not handle this key event.
7181 consumeKey(/*handled=*/false,
7182 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7183 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7184 // App does not handle the fallback either, so ensure another fallback is not generated.
7185 setFallback(AKEYCODE_C);
7186 consumeKey(/*handled=*/false,
7187 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7188 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7189
7190 // Release the original key, and ensure the fallback key is also released.
7191 setFallback(AKEYCODE_B);
7192 mDispatcher->notifyKey(
7193 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7194 consumeKey(/*handled=*/false,
7195 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7196 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7197 consumeKey(/*handled=*/false,
7198 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7199 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7200
7201 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7202 mWindow->assertNoEvents();
7203}
7204
7205TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
7206 setFallback(AKEYCODE_B);
7207 mDispatcher->notifyKey(
7208 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7209
7210 // Do not handle this key event, so fallback is generated.
7211 consumeKey(/*handled=*/false,
7212 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7213 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7214 consumeKey(/*handled=*/true,
7215 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7216 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7217
7218 // Release the original key, but assume the policy is misbehaving and it
7219 // generates an inconsistent fallback to the one from the DOWN event.
7220 setFallback(AKEYCODE_C);
7221 mDispatcher->notifyKey(
7222 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7223 consumeKey(/*handled=*/false,
7224 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7225 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7226 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
7227 consumeKey(/*handled=*/true,
7228 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7229 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7230
7231 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7232 mWindow->assertNoEvents();
7233}
7234
7235TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
7236 setFallback(AKEYCODE_B);
7237 mDispatcher->notifyKey(
7238 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7239
7240 // Do not handle this key event, so fallback is generated.
7241 consumeKey(/*handled=*/false,
7242 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7243 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7244 consumeKey(/*handled=*/true,
7245 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7246 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7247
7248 // The original key is canceled.
7249 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7250 .keyCode(AKEYCODE_A)
7251 .addFlag(AKEY_EVENT_FLAG_CANCELED)
7252 .build());
7253 consumeKey(/*handled=*/false,
7254 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7255 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7256 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7257 // Ensure the fallback key is also canceled due to the original key being canceled.
7258 consumeKey(/*handled=*/true,
7259 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7260 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7261
7262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
7263 mWindow->assertNoEvents();
7264}
7265
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007266TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00007267 setFallback(AKEYCODE_B);
7268 mDispatcher->notifyKey(
7269 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7270
7271 // Do not handle this key event.
7272 consumeKey(/*handled=*/false,
7273 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7274 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7275 consumeKey(/*handled=*/true,
7276 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7277 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7278
7279 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7280 // When the unhandled key is reported to the policy next, remove the input channel.
7281 mDispatcher->removeInputChannel(mWindow->getToken());
7282 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7283 });
7284 // Release the original key, and let the app now handle the previously unhandled key.
7285 // This should result in the previously generated fallback key to be cancelled.
7286 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
7287 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
7288 // without holding the lock, because it need to synchronously fetch the fallback key. While in
7289 // the policy call, we will now remove the input channel. Once the policy call returns, the
7290 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
7291 // not cause any crashes.
7292 mDispatcher->notifyKey(
7293 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7294 consumeKey(/*handled=*/true,
7295 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7296 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7297}
7298
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00007299TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
7300 setFallback(AKEYCODE_B);
7301 mDispatcher->notifyKey(
7302 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7303
7304 // Do not handle this key event.
7305 consumeKey(/*handled=*/false,
7306 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7307 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7308 consumeKey(/*handled=*/true,
7309 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7310 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7311
7312 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
7313 // When the unhandled key is reported to the policy next, remove the window.
7314 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7315 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
7316 });
7317 // Release the original key, which the app will not handle. When this unhandled key is reported
7318 // to the policy, the window will be removed.
7319 mDispatcher->notifyKey(
7320 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7321 consumeKey(/*handled=*/false,
7322 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7323 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7324
7325 // Since the window was removed, it loses focus, and the channel state will be reset.
7326 consumeKey(/*handled=*/true,
7327 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7328 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7329 mWindow->consumeFocusEvent(false);
7330 mWindow->assertNoEvents();
7331}
7332
7333TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
7334 setFallback(AKEYCODE_B);
7335 mDispatcher->notifyKey(
7336 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
7337
7338 // Do not handle this key event.
7339 consumeKey(/*handled=*/false,
7340 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
7341 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
7342 const auto [seq, event] = mWindow->receiveEvent();
7343 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
7344 ASSERT_EQ(event->getType(), InputEventType::KEY);
7345 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
7346 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
7347 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
7348
7349 // Remove the window now, which should generate a cancellations and make the window lose focus.
7350 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7351 consumeKey(/*handled=*/true,
7352 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7353 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7354 consumeKey(/*handled=*/true,
7355 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7356 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7357 mWindow->consumeFocusEvent(false);
7358
7359 // Finish the event by reporting it as handled.
7360 mWindow->finishEvent(*seq);
7361 mWindow->assertNoEvents();
7362}
7363
Garfield Tan1c7bc862020-01-28 13:24:04 -08007364class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7365protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007366 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7367 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007368
Chris Yea209fde2020-07-22 13:54:51 -07007369 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007370 sp<FakeWindowHandle> mWindow;
7371
7372 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007373 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007374
Prabir Pradhandae52792023-12-15 07:36:40 +00007375 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007376 setUpWindow();
7377 }
7378
7379 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007380 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007381 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007382
Vishnu Nair47074b82020-08-14 11:54:47 -07007383 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007384 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007385 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007386 mWindow->consumeFocusEvent(true);
7387 }
7388
Chris Ye2ad95392020-09-01 13:44:44 -07007389 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007390 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007391 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007392 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007393 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007394
7395 // Window should receive key down event.
7396 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7397 }
7398
7399 void expectKeyRepeatOnce(int32_t repeatCount) {
7400 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007401 mWindow->consumeKeyEvent(
7402 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007403 }
7404
Chris Ye2ad95392020-09-01 13:44:44 -07007405 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007406 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007407 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007408 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007409 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007410
7411 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007412 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007413 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007414 }
7415};
7416
7417TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007418 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007419 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7420 expectKeyRepeatOnce(repeatCount);
7421 }
7422}
7423
7424TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007425 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007426 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7427 expectKeyRepeatOnce(repeatCount);
7428 }
Harry Cutts33476232023-01-30 19:57:29 +00007429 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007430 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007431 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7432 expectKeyRepeatOnce(repeatCount);
7433 }
7434}
7435
7436TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007437 sendAndConsumeKeyDown(/*deviceId=*/1);
7438 expectKeyRepeatOnce(/*repeatCount=*/1);
7439 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007440 mWindow->assertNoEvents();
7441}
7442
7443TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007444 sendAndConsumeKeyDown(/*deviceId=*/1);
7445 expectKeyRepeatOnce(/*repeatCount=*/1);
7446 sendAndConsumeKeyDown(/*deviceId=*/2);
7447 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007448 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007449 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007450 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007451 expectKeyRepeatOnce(/*repeatCount=*/2);
7452 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007453 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007454 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007455 mWindow->assertNoEvents();
7456}
7457
7458TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007459 sendAndConsumeKeyDown(/*deviceId=*/1);
7460 expectKeyRepeatOnce(/*repeatCount=*/1);
7461 sendAndConsumeKeyDown(/*deviceId=*/2);
7462 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007463 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007464 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007465 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007466 mWindow->assertNoEvents();
7467}
7468
liushenxiang42232912021-05-21 20:24:09 +08007469TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7470 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007471 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007472 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007473 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7474 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7475 mWindow->assertNoEvents();
7476}
7477
Garfield Tan1c7bc862020-01-28 13:24:04 -08007478TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007479 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007480 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007481 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007482 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7483 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007484 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007485 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007486 }
7487}
7488
7489TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007490 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007491 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007492
7493 std::unordered_set<int32_t> idSet;
7494 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007495 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7496 ASSERT_NE(nullptr, repeatEvent);
7497 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007498 EXPECT_EQ(idSet.end(), idSet.find(id));
7499 idSet.insert(id);
7500 }
7501}
7502
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007503/* Test InputDispatcher for MultiDisplay */
7504class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7505public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007506 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007507 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007508
Chris Yea209fde2020-07-22 13:54:51 -07007509 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007510 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007511 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007512
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007513 // Set focus window for primary display, but focused display would be second one.
7514 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007515 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007516 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7517
Vishnu Nair958da932020-08-21 17:12:37 -07007518 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007519 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007520
Chris Yea209fde2020-07-22 13:54:51 -07007521 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007522 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007523 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007524 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007525 // Set focus display to second one.
7526 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7527 // Set focus window for second display.
7528 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007529 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007530 mDispatcher->onWindowInfosChanged(
7531 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007532 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007533 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007534 }
7535
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007536 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007537 InputDispatcherTest::TearDown();
7538
Chris Yea209fde2020-07-22 13:54:51 -07007539 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007540 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007541 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007542 windowInSecondary.clear();
7543 }
7544
7545protected:
Chris Yea209fde2020-07-22 13:54:51 -07007546 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007547 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007548 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007549 sp<FakeWindowHandle> windowInSecondary;
7550};
7551
7552TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7553 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007555 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007557 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007558 windowInSecondary->assertNoEvents();
7559
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007560 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007561 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007562 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007563 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007564 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007565 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007566}
7567
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007568TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007569 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007571 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007572 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007573 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007574 windowInSecondary->assertNoEvents();
7575
7576 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007578 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007579 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007580 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007581
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007582 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007583 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007584
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007585 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007586 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007587
7588 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007589 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007590 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007591 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007592 windowInSecondary->assertNoEvents();
7593}
7594
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007595// Test per-display input monitors for motion event.
7596TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007597 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007598 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007599 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007600 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007601
7602 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007604 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007606 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007607 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007608 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007609 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007610
7611 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007613 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007614 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007615 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007616 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007617 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007618 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007619
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007620 // Lift up the touch from the second display
7621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007622 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007623 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7624 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7625 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7626
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007627 // Test inject a non-pointer motion event.
7628 // If specific a display, it will dispatch to the focused window of particular display,
7629 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007631 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007633 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007634 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007635 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007636 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007637}
7638
7639// Test per-display input monitors for key event.
7640TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007641 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007642 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007643 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007644 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007645 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007646
7647 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007649 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007650 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007651 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007652 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007653 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007654}
7655
Vishnu Nair958da932020-08-21 17:12:37 -07007656TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7657 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007658 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007659 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007660 mDispatcher->onWindowInfosChanged(
7661 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7662 *windowInSecondary->getInfo()},
7663 {},
7664 0,
7665 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007666 setFocusedWindow(secondWindowInPrimary);
7667 windowInPrimary->consumeFocusEvent(false);
7668 secondWindowInPrimary->consumeFocusEvent(true);
7669
7670 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7672 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007673 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007674 windowInPrimary->assertNoEvents();
7675 windowInSecondary->assertNoEvents();
7676 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7677}
7678
Arthur Hungdfd528e2021-12-08 13:23:04 +00007679TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7680 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007681 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007682 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007683 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007684
7685 // Test touch down on primary display.
7686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7689 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7690 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7691
7692 // Test touch down on second display.
7693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007694 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7696 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7697 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7698
7699 // Trigger cancel touch.
7700 mDispatcher->cancelCurrentTouch();
7701 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7702 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7703 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7704 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7705
7706 // Test inject a move motion event, no window/monitor should receive the event.
7707 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007708 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007709 ADISPLAY_ID_DEFAULT, {110, 200}))
7710 << "Inject motion event should return InputEventInjectionResult::FAILED";
7711 windowInPrimary->assertNoEvents();
7712 monitorInPrimary.assertNoEvents();
7713
7714 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007715 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007716 SECOND_DISPLAY_ID, {110, 200}))
7717 << "Inject motion event should return InputEventInjectionResult::FAILED";
7718 windowInSecondary->assertNoEvents();
7719 monitorInSecondary.assertNoEvents();
7720}
7721
Hu Guocb134f12023-12-23 13:42:44 +00007722/**
7723 * Send a key to the primary display and to the secondary display.
7724 * Then cause the key on the primary display to be canceled by sending in a stale key.
7725 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7726 * does not get canceled.
7727 */
7728TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7729 // Send a key down on primary display
7730 mDispatcher->notifyKey(
7731 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7732 .displayId(ADISPLAY_ID_DEFAULT)
7733 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7734 .build());
7735 windowInPrimary->consumeKeyEvent(
7736 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7737 windowInSecondary->assertNoEvents();
7738
7739 // Send a key down on second display
7740 mDispatcher->notifyKey(
7741 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7742 .displayId(SECOND_DISPLAY_ID)
7743 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7744 .build());
7745 windowInSecondary->consumeKeyEvent(
7746 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7747 windowInPrimary->assertNoEvents();
7748
7749 // Send a valid key up event on primary display that will be dropped because it is stale
7750 NotifyKeyArgs staleKeyUp =
7751 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7752 .displayId(ADISPLAY_ID_DEFAULT)
7753 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7754 .build();
7755 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7756 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7757 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7758 mDispatcher->notifyKey(staleKeyUp);
7759
7760 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7761 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7762 // receive any events.
7763 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7764 WithDisplayId(ADISPLAY_ID_DEFAULT),
7765 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7766 windowInSecondary->assertNoEvents();
7767}
7768
7769/**
7770 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7771 */
7772TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7773 // Send touch down on primary display.
7774 mDispatcher->notifyMotion(
7775 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7776 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7777 .displayId(ADISPLAY_ID_DEFAULT)
7778 .build());
7779 windowInPrimary->consumeMotionEvent(
7780 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7781 windowInSecondary->assertNoEvents();
7782
7783 // Send touch down on second display.
7784 mDispatcher->notifyMotion(
7785 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7786 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7787 .displayId(SECOND_DISPLAY_ID)
7788 .build());
7789 windowInPrimary->assertNoEvents();
7790 windowInSecondary->consumeMotionEvent(
7791 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7792
7793 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7794 NotifyMotionArgs staleMotionUp =
7795 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7796 .displayId(ADISPLAY_ID_DEFAULT)
7797 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7798 .build();
7799 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7800 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7801 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7802 mDispatcher->notifyMotion(staleMotionUp);
7803
7804 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7805 // events, where we would cancel the current keys instead.
7806 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7807 windowInSecondary->assertNoEvents();
7808}
7809
Jackal Guof9696682018-10-05 12:23:23 +08007810class InputFilterTest : public InputDispatcherTest {
7811protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007812 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7813 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007814 NotifyMotionArgs motionArgs;
7815
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007816 motionArgs =
7817 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007818 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007819 motionArgs =
7820 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007821 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007822 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007823 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007824 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007825 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007826 } else {
7827 mFakePolicy->assertFilterInputEventWasNotCalled();
7828 }
7829 }
7830
7831 void testNotifyKey(bool expectToBeFiltered) {
7832 NotifyKeyArgs keyArgs;
7833
7834 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007835 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007836 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007837 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007838 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007839
7840 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007841 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007842 } else {
7843 mFakePolicy->assertFilterInputEventWasNotCalled();
7844 }
7845 }
7846};
7847
7848// Test InputFilter for MotionEvent
7849TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7850 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007851 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7852 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007853
7854 // Enable InputFilter
7855 mDispatcher->setInputFilterEnabled(true);
7856 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007857 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7858 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007859
7860 // Disable InputFilter
7861 mDispatcher->setInputFilterEnabled(false);
7862 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007863 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7864 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007865}
7866
7867// Test InputFilter for KeyEvent
7868TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7869 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007870 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007871
7872 // Enable InputFilter
7873 mDispatcher->setInputFilterEnabled(true);
7874 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007875 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007876
7877 // Disable InputFilter
7878 mDispatcher->setInputFilterEnabled(false);
7879 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007880 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007881}
7882
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007883// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7884// logical display coordinate space.
7885TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7886 ui::Transform firstDisplayTransform;
7887 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7888 ui::Transform secondDisplayTransform;
7889 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7890
7891 std::vector<gui::DisplayInfo> displayInfos(2);
7892 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7893 displayInfos[0].transform = firstDisplayTransform;
7894 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7895 displayInfos[1].transform = secondDisplayTransform;
7896
Patrick Williamsd828f302023-04-28 17:52:08 -05007897 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007898
7899 // Enable InputFilter
7900 mDispatcher->setInputFilterEnabled(true);
7901
7902 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007903 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7904 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007905}
7906
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007907class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7908protected:
7909 virtual void SetUp() override {
7910 InputDispatcherTest::SetUp();
7911
7912 /**
7913 * We don't need to enable input filter to test the injected event policy, but we enabled it
7914 * here to make the tests more realistic, since this policy only matters when inputfilter is
7915 * on.
7916 */
7917 mDispatcher->setInputFilterEnabled(true);
7918
7919 std::shared_ptr<InputApplicationHandle> application =
7920 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007921 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7922 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007923
7924 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7925 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007926 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007927 setFocusedWindow(mWindow);
7928 mWindow->consumeFocusEvent(true);
7929 }
7930
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007931 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7932 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007933 KeyEvent event;
7934
7935 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7936 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7937 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007938 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007939 const int32_t additionalPolicyFlags =
7940 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007942 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007943 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007944 policyFlags | additionalPolicyFlags));
7945
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007946 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007947 }
7948
7949 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7950 int32_t flags) {
7951 MotionEvent event;
7952 PointerProperties pointerProperties[1];
7953 PointerCoords pointerCoords[1];
7954 pointerProperties[0].clear();
7955 pointerProperties[0].id = 0;
7956 pointerCoords[0].clear();
7957 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7958 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7959
7960 ui::Transform identityTransform;
7961 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7962 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7963 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7964 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7965 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007966 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007967 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007968 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007969
7970 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007972 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007973 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007974 policyFlags | additionalPolicyFlags));
7975
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007976 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007977 }
7978
7979private:
7980 sp<FakeWindowHandle> mWindow;
7981};
7982
7983TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007984 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7985 // filter. Without it, the event will no different from a regularly injected event, and the
7986 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007987 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7988 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007989}
7990
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007991TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007992 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007993 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007994 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7995}
7996
7997TEST_F(InputFilterInjectionPolicyTest,
7998 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7999 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00008000 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008001 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008002}
8003
8004TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00008005 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
8006 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008007}
8008
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008009class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
8010protected:
8011 virtual void SetUp() override {
8012 InputDispatcherTest::SetUp();
8013
8014 std::shared_ptr<FakeApplicationHandle> application =
8015 std::make_shared<FakeApplicationHandle>();
8016 application->setDispatchingTimeout(100ms);
8017 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8018 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00008019 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08008020 mWindow->setDispatchingTimeout(100ms);
8021 mWindow->setFocusable(true);
8022
8023 // Set focused application.
8024 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
8025
8026 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8027 setFocusedWindow(mWindow);
8028 mWindow->consumeFocusEvent(true);
8029 }
8030
8031 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
8032 nsecs_t eventTime) {
8033 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
8034 .displayId(displayId)
8035 .eventTime(eventTime)
8036 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8037 .build());
8038 mWindow->consumeMotionEvent(WithMotionAction(action));
8039 }
8040
8041private:
8042 sp<FakeWindowHandle> mWindow;
8043};
8044
8045TEST_F_WITH_FLAGS(
8046 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
8047 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8048 rate_limit_user_activity_poke_in_dispatcher))) {
8049 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
8050
8051 // First event of type TOUCH. Should poke.
8052 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8053 milliseconds_to_nanoseconds(50));
8054 mFakePolicy->assertUserActivityPoked(
8055 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8056
8057 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
8058 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8059 milliseconds_to_nanoseconds(130));
8060 mFakePolicy->assertUserActivityPoked(
8061 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8062
8063 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
8064 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8065 milliseconds_to_nanoseconds(135));
8066 mFakePolicy->assertUserActivityPoked(
8067 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8068
8069 // Within 50ns of previous TOUCH event. Should NOT poke.
8070 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8071 milliseconds_to_nanoseconds(140));
8072 mFakePolicy->assertUserActivityNotPoked();
8073
8074 // Within 50ns of previous OTHER event. Should NOT poke.
8075 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8076 milliseconds_to_nanoseconds(150));
8077 mFakePolicy->assertUserActivityNotPoked();
8078
8079 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
8080 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
8081 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8082 milliseconds_to_nanoseconds(160));
8083 mFakePolicy->assertUserActivityNotPoked();
8084
8085 // 65ns > 50ns has passed since previous OTHER event. Should poke.
8086 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
8087 milliseconds_to_nanoseconds(200));
8088 mFakePolicy->assertUserActivityPoked(
8089 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
8090
8091 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
8092 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
8093 milliseconds_to_nanoseconds(300));
8094 mFakePolicy->assertUserActivityPoked(
8095 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8096
8097 // Assert that there's no more user activity poke event.
8098 mFakePolicy->assertUserActivityNotPoked();
8099}
8100
8101TEST_F_WITH_FLAGS(
8102 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
8103 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8104 rate_limit_user_activity_poke_in_dispatcher))) {
8105 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8106 milliseconds_to_nanoseconds(200));
8107 mFakePolicy->assertUserActivityPoked(
8108 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8109
8110 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8111 milliseconds_to_nanoseconds(280));
8112 mFakePolicy->assertUserActivityNotPoked();
8113
8114 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8115 milliseconds_to_nanoseconds(340));
8116 mFakePolicy->assertUserActivityPoked(
8117 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
8118}
8119
8120TEST_F_WITH_FLAGS(
8121 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
8122 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
8123 rate_limit_user_activity_poke_in_dispatcher))) {
8124 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
8125
8126 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
8127 mFakePolicy->assertUserActivityPoked();
8128
8129 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
8130 mFakePolicy->assertUserActivityPoked();
8131}
8132
chaviwfd6d3512019-03-25 13:23:49 -07008133class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008134 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07008135 InputDispatcherTest::SetUp();
8136
Chris Yea209fde2020-07-22 13:54:51 -07008137 std::shared_ptr<FakeApplicationHandle> application =
8138 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008139 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008140 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008141 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07008142
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008143 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008144 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008145 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07008146
8147 // Set focused application.
8148 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008149 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07008150
8151 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008152 mDispatcher->onWindowInfosChanged(
8153 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008154 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008155 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07008156 }
8157
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008158 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07008159 InputDispatcherTest::TearDown();
8160
8161 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008162 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07008163 }
8164
8165protected:
8166 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008167 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008168 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07008169};
8170
8171// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8172// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
8173// the onPointerDownOutsideFocus callback.
8174TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008176 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008177 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008178 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008179 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008180
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008181 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07008182 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
8183}
8184
8185// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
8186// DOWN on the window that doesn't have focus. Ensure no window received the
8187// onPointerDownOutsideFocus callback.
8188TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008190 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
8191 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008193 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008194
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008195 ASSERT_TRUE(mDispatcher->waitForIdle());
8196 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008197}
8198
8199// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
8200// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
8201TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008202 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008203 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008204 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008205 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07008206
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008207 ASSERT_TRUE(mDispatcher->waitForIdle());
8208 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008209}
8210
8211// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
8212// DOWN on the window that already has focus. Ensure no window received the
8213// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008214TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008216 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07008217 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008218 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07008219 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07008220
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008221 ASSERT_TRUE(mDispatcher->waitForIdle());
8222 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07008223}
8224
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008225// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
8226// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
8227TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
8228 const MotionEvent event =
8229 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
8230 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07008231 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008232 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
8233 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08008235 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8236 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
8237
8238 ASSERT_TRUE(mDispatcher->waitForIdle());
8239 mFakePolicy->assertOnPointerDownWasNotCalled();
8240 // Ensure that the unfocused window did not receive any FOCUS events.
8241 mUnfocusedWindow->assertNoEvents();
8242}
8243
chaviwaf87b3e2019-10-01 16:59:28 -07008244// These tests ensures we can send touch events to a single client when there are multiple input
8245// windows that point to the same client token.
8246class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
8247 virtual void SetUp() override {
8248 InputDispatcherTest::SetUp();
8249
Chris Yea209fde2020-07-22 13:54:51 -07008250 std::shared_ptr<FakeApplicationHandle> application =
8251 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008252 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
8253 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008254 mWindow1->setFrame(Rect(0, 0, 100, 100));
8255
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00008256 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07008257 mWindow2->setFrame(Rect(100, 100, 200, 200));
8258
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008259 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008260 }
8261
8262protected:
8263 sp<FakeWindowHandle> mWindow1;
8264 sp<FakeWindowHandle> mWindow2;
8265
8266 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05008267 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07008268 vec2 vals = windowInfo->transform.transform(point.x, point.y);
8269 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07008270 }
8271
8272 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
8273 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008274 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008275 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008276 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008277 ASSERT_NE(nullptr, motionEvent);
8278 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07008279
8280 for (size_t i = 0; i < points.size(); i++) {
8281 float expectedX = points[i].x;
8282 float expectedY = points[i].y;
8283
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008284 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008285 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008286 << ", got " << motionEvent->getX(i);
8287 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07008288 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008289 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07008290 }
8291 }
chaviw9eaa22c2020-07-01 16:21:27 -07008292
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008293 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
8294 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07008295 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00008296 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
8297 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07008298
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008299 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008300 }
chaviwaf87b3e2019-10-01 16:59:28 -07008301};
8302
8303TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
8304 // Touch Window 1
8305 PointF touchedPoint = {10, 10};
8306 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008307 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008308
8309 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008310 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008311
8312 // Touch Window 2
8313 touchedPoint = {150, 150};
8314 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008315 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008316}
8317
chaviw9eaa22c2020-07-01 16:21:27 -07008318TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
8319 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07008320 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008321 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07008322
8323 // Touch Window 1
8324 PointF touchedPoint = {10, 10};
8325 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008326 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008327 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008328 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008329
8330 // Touch Window 2
8331 touchedPoint = {150, 150};
8332 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008333 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8334 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008335
chaviw9eaa22c2020-07-01 16:21:27 -07008336 // Update the transform so rotation is set
8337 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008338 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008339 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008340 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008341}
8342
chaviw9eaa22c2020-07-01 16:21:27 -07008343TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008344 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008345 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008346
8347 // Touch Window 1
8348 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8349 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008350 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008351
8352 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008353 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8354 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8355 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008356 touchedPoints.push_back(PointF{150, 150});
8357 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008358 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008359
chaviw9eaa22c2020-07-01 16:21:27 -07008360 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008361 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008362 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008363
chaviw9eaa22c2020-07-01 16:21:27 -07008364 // Update the transform so rotation is set for Window 2
8365 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008366 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008367 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008368 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008369}
8370
chaviw9eaa22c2020-07-01 16:21:27 -07008371TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008372 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008373 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008374
8375 // Touch Window 1
8376 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8377 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008378 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008379
8380 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008381 touchedPoints.push_back(PointF{150, 150});
8382 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008383
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008384 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008385
8386 // Move both windows
8387 touchedPoints = {{20, 20}, {175, 175}};
8388 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8389 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8390
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008391 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008392
chaviw9eaa22c2020-07-01 16:21:27 -07008393 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008394 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008395 expectedPoints.pop_back();
8396
8397 // Touch Window 2
8398 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008399 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008400 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008401 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008402
8403 // Move both windows
8404 touchedPoints = {{20, 20}, {175, 175}};
8405 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8406 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8407
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008408 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008409}
8410
8411TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8412 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008413 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008414
8415 // Touch Window 1
8416 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8417 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008418 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008419
8420 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008421 touchedPoints.push_back(PointF{150, 150});
8422 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008423
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008424 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008425
8426 // Move both windows
8427 touchedPoints = {{20, 20}, {175, 175}};
8428 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8429 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8430
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008431 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008432}
8433
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008434/**
8435 * When one of the windows is slippery, the touch should not slip into the other window with the
8436 * same input channel.
8437 */
8438TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8439 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008440 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008441
8442 // Touch down in window 1
8443 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8444 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8445 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8446
8447 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8448 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8449 // getting generated.
8450 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8451 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8452
8453 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8454}
8455
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008456/**
8457 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8458 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8459 * that the pointer is hovering over may have a different transform.
8460 */
8461TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008462 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008463
8464 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008465 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8466 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8467 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008468 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8469 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008470 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8472 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8473 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008474 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008475 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008476 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8477}
8478
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008479class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8480 virtual void SetUp() override {
8481 InputDispatcherTest::SetUp();
8482
Chris Yea209fde2020-07-22 13:54:51 -07008483 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008484 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008485 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8486 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008487 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008488 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008489 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008490
8491 // Set focused application.
8492 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8493
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008494 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008495 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008496 mWindow->consumeFocusEvent(true);
8497 }
8498
8499 virtual void TearDown() override {
8500 InputDispatcherTest::TearDown();
8501 mWindow.clear();
8502 }
8503
8504protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008505 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008506 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008507 sp<FakeWindowHandle> mWindow;
8508 static constexpr PointF WINDOW_LOCATION = {20, 20};
8509
8510 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008511 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8512 .x(WINDOW_LOCATION.x)
8513 .y(WINDOW_LOCATION.y);
8514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8515 .pointer(touchingPointer)
8516 .build());
8517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8518 .pointer(touchingPointer)
8519 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008520 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008521
8522 sp<FakeWindowHandle> addSpyWindow() {
8523 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008524 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008525 spy->setTrustedOverlay(true);
8526 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008527 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008528 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008529 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008530 return spy;
8531 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008532};
8533
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008534// Send a tap and respond, which should not cause an ANR.
8535TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8536 tapOnWindow();
8537 mWindow->consumeMotionDown();
8538 mWindow->consumeMotionUp();
8539 ASSERT_TRUE(mDispatcher->waitForIdle());
8540 mFakePolicy->assertNotifyAnrWasNotCalled();
8541}
8542
8543// Send a regular key and respond, which should not cause an ANR.
8544TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008546 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8547 ASSERT_TRUE(mDispatcher->waitForIdle());
8548 mFakePolicy->assertNotifyAnrWasNotCalled();
8549}
8550
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008551TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8552 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008553 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008554 mWindow->consumeFocusEvent(false);
8555
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008556 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008557 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8558 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008559 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008561 // Key will not go to window because we have no focused window.
8562 // The 'no focused window' ANR timer should start instead.
8563
8564 // Now, the focused application goes away.
8565 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8566 // The key should get dropped and there should be no ANR.
8567
8568 ASSERT_TRUE(mDispatcher->waitForIdle());
8569 mFakePolicy->assertNotifyAnrWasNotCalled();
8570}
8571
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008572// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008573// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8574// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008575TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008577 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008578 WINDOW_LOCATION));
8579
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008580 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008581 ASSERT_TRUE(sequenceNum);
8582 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008583 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008584
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008585 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008586 mWindow->consumeMotionEvent(
8587 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008588 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008589 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008590}
8591
8592// Send a key to the app and have the app not respond right away.
8593TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8594 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008596 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008597 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008598 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008599 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008600 ASSERT_TRUE(mDispatcher->waitForIdle());
8601}
8602
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008603// We have a focused application, but no focused window
8604TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008605 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008606 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008607 mWindow->consumeFocusEvent(false);
8608
8609 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008611 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008612 WINDOW_LOCATION));
8613 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8614 mDispatcher->waitForIdle();
8615 mFakePolicy->assertNotifyAnrWasNotCalled();
8616
8617 // Once a focused event arrives, we get an ANR for this application
8618 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8619 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008620 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008621 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008622 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008623 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008624 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008625 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008626 ASSERT_TRUE(mDispatcher->waitForIdle());
8627}
8628
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008629/**
8630 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8631 * there will not be an ANR.
8632 */
8633TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8634 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008635 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008636 mWindow->consumeFocusEvent(false);
8637
8638 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008639 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8640 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008641 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8642 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8643
8644 // Define a valid key down event that is stale (too old).
8645 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008646 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Harry Cutts33476232023-01-30 19:57:29 +00008647 AMETA_NONE, /*repeatCount=*/1, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008648
8649 const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
8650
8651 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008652 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008653 InputEventInjectionSync::WAIT_FOR_RESULT,
8654 INJECT_EVENT_TIMEOUT, policyFlags);
8655 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8656 << "Injection should fail because the event is stale";
8657
8658 ASSERT_TRUE(mDispatcher->waitForIdle());
8659 mFakePolicy->assertNotifyAnrWasNotCalled();
8660 mWindow->assertNoEvents();
8661}
8662
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008663// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008664// Make sure that we don't notify policy twice about the same ANR.
8665TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008666 const std::chrono::duration appTimeout = 400ms;
8667 mApplication->setDispatchingTimeout(appTimeout);
8668 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8669
Vishnu Nair47074b82020-08-14 11:54:47 -07008670 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008671 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008672 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008673
8674 // Once a focused event arrives, we get an ANR for this application
8675 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8676 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008677 const std::chrono::duration eventInjectionTimeout = 100ms;
8678 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008679 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008680 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008681 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8682 /*allowKeyRepeat=*/false);
8683 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8684 << "result=" << ftl::enum_string(result);
8685 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8686 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8687 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8688 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008689
Vishnu Naire4df8752022-09-08 09:17:55 -07008690 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008691 // ANR should not be raised again. It is up to policy to do that if it desires.
8692 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008693
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008694 // If we now get a focused window, the ANR should stop, but the policy handles that via
8695 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008696 ASSERT_TRUE(mDispatcher->waitForIdle());
8697}
8698
8699// We have a focused application, but no focused window
8700TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008701 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008702 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008703 mWindow->consumeFocusEvent(false);
8704
8705 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008706 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008707
Vishnu Naire4df8752022-09-08 09:17:55 -07008708 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8709 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008710
8711 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008712 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008713 ASSERT_TRUE(mDispatcher->waitForIdle());
8714 mWindow->assertNoEvents();
8715}
8716
8717/**
8718 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8719 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8720 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8721 * the ANR mechanism should still work.
8722 *
8723 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8724 * DOWN event, while not responding on the second one.
8725 */
8726TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8727 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008728 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008729 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8730 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8731 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008732 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008733
8734 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008735 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008736 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8737 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8738 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008739 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008740
8741 // We have now sent down and up. Let's consume first event and then ANR on the second.
8742 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8743 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008744 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008745}
8746
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008747// A spy window can receive an ANR
8748TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8749 sp<FakeWindowHandle> spy = addSpyWindow();
8750
8751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008752 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008753 WINDOW_LOCATION));
8754 mWindow->consumeMotionDown();
8755
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008756 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008757 ASSERT_TRUE(sequenceNum);
8758 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008759 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008760
8761 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008762 spy->consumeMotionEvent(
8763 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008764 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008765 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008766}
8767
8768// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008769// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008770TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8771 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008772
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008774 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008775 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008777
8778 // Stuck on the ACTION_UP
8779 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008780 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008781
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008782 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008783 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008784 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8785 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008786
8787 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8788 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008789 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008790 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008791 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008792}
8793
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008794// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008795// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008796TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8797 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008798
8799 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008800 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8801 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008802
8803 mWindow->consumeMotionDown();
8804 // Stuck on the ACTION_UP
8805 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008806 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008807
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008808 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008809 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008810 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8811 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008812
8813 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8814 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008815 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008816 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008817 spy->assertNoEvents();
8818}
8819
8820TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008821 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008822
Prabir Pradhanfb549072023-10-05 19:17:36 +00008823 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008824
8825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008826 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008827 WINDOW_LOCATION));
8828
8829 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8830 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8831 ASSERT_TRUE(consumeSeq);
8832
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008833 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8834 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008835
8836 monitor.finishEvent(*consumeSeq);
8837 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8838
8839 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008840 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008841}
8842
8843// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8844// process events, you don't get an anr. When the window later becomes unresponsive again, you
8845// get an ANR again.
8846// 1. tap -> block on ACTION_UP -> receive ANR
8847// 2. consume all pending events (= queue becomes healthy again)
8848// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8849TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8850 tapOnWindow();
8851
8852 mWindow->consumeMotionDown();
8853 // Block on ACTION_UP
8854 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008855 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008856 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8857 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008858 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008859 mWindow->assertNoEvents();
8860
8861 tapOnWindow();
8862 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008863 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008864 mWindow->consumeMotionUp();
8865
8866 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008867 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008868 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008869 mWindow->assertNoEvents();
8870}
8871
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008872// If a connection remains unresponsive for a while, make sure policy is only notified once about
8873// it.
8874TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008877 WINDOW_LOCATION));
8878
8879 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008880 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008881 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008882 // 'notifyConnectionUnresponsive' should only be called once per connection
8883 mFakePolicy->assertNotifyAnrWasNotCalled();
8884 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008885 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008886 mWindow->consumeMotionEvent(
8887 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008888 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008889 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008890 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008891 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008892}
8893
8894/**
8895 * 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 -07008896 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008897 */
8898TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008899 // The timeouts in this test are established by relying on the fact that the "key waiting for
8900 // events timeout" is equal to 500ms.
8901 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008902 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008903 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008904
8905 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008906 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008907 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008908 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008909 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008910
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008911 // Don't finish the events yet, and send a key
8912 mDispatcher->notifyKey(
8913 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8914 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8915 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008916 // Key will not be sent to the window, yet, because the window is still processing events
8917 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008918 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008919 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008920
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008921 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008922 // if we wait long enough though, dispatcher will give up, and still send the key
8923 // to the focused window, even though we have not yet finished the motion event
8924 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8925 mWindow->finishEvent(*downSequenceNum);
8926 mWindow->finishEvent(*upSequenceNum);
8927}
8928
8929/**
8930 * If a window is processing a motion event, and then a key event comes in, the key event should
8931 * not go to the focused window until the motion is processed.
8932 * If then a new motion comes in, then the pending key event should be going to the currently
8933 * focused window right away.
8934 */
8935TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008936 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
8937 // The timeouts in this test are established by relying on the fact that the "key waiting for
8938 // events timeout" is equal to 500ms.
8939 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008940 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008941 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008942
8943 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008944 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008945 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008946 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008947 ASSERT_TRUE(upSequenceNum);
8948 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008949 mDispatcher->notifyKey(
8950 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8951 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8952 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008953 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008954 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008955
8956 // Now tap down again. It should cause the pending key to go to the focused window right away.
8957 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008958 // Now that we tapped, we should receive the key immediately.
8959 // Since there's still room for slowness, we use 200ms, which is much less than
8960 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
8961 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
8962 ASSERT_NE(nullptr, keyEvent);
8963 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
8964 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
8965 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
8966 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008967 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8968 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008969 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8970 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008971 mWindow->assertNoEvents();
8972}
8973
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008974/**
8975 * Send an event to the app and have the app not respond right away.
8976 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8977 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8978 * At some point, the window becomes responsive again.
8979 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8980 */
8981TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8982 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8983 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8984 .build());
8985
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008986 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008987 ASSERT_TRUE(sequenceNum);
8988 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8989 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8990
8991 mWindow->finishEvent(*sequenceNum);
8992 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8993 ASSERT_TRUE(mDispatcher->waitForIdle());
8994 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8995
8996 // Now that the window is responsive, let's continue the gesture.
8997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8998 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8999 .build());
9000
9001 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9002 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9003 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9004 .build());
9005
9006 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
9007 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9008 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
9009 .build());
9010 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9011 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
9012 .build());
9013 // We already canceled this pointer, so the window shouldn't get any new events.
9014 mWindow->assertNoEvents();
9015
9016 // Start another one.
9017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9018 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
9019 .build());
9020 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9021}
9022
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009023class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
9024 virtual void SetUp() override {
9025 InputDispatcherTest::SetUp();
9026
Chris Yea209fde2020-07-22 13:54:51 -07009027 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009028 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009029 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
9030 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009031 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009032 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009033 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009034
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009035 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
9036 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009037 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009038 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009039
9040 // Set focused application.
9041 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07009042 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009043
9044 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009045 mDispatcher->onWindowInfosChanged(
9046 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009047 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009048 mFocusedWindow->consumeFocusEvent(true);
9049 }
9050
9051 virtual void TearDown() override {
9052 InputDispatcherTest::TearDown();
9053
9054 mUnfocusedWindow.clear();
9055 mFocusedWindow.clear();
9056 }
9057
9058protected:
Chris Yea209fde2020-07-22 13:54:51 -07009059 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009060 sp<FakeWindowHandle> mUnfocusedWindow;
9061 sp<FakeWindowHandle> mFocusedWindow;
9062 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
9063 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
9064 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
9065
9066 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
9067
9068 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
9069
9070private:
9071 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009072 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009073 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009074 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009076 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009077 location));
9078 }
9079};
9080
9081// If we have 2 windows that are both unresponsive, the one with the shortest timeout
9082// should be ANR'd first.
9083TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009085 injectMotionEvent(*mDispatcher,
9086 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9087 AINPUT_SOURCE_TOUCHSCREEN)
9088 .pointer(PointerBuilder(0, ToolType::FINGER)
9089 .x(FOCUSED_WINDOW_LOCATION.x)
9090 .y(FOCUSED_WINDOW_LOCATION.y))
9091 .build()));
9092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9093 injectMotionEvent(*mDispatcher,
9094 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
9095 AINPUT_SOURCE_TOUCHSCREEN)
9096 .pointer(PointerBuilder(0, ToolType::FINGER)
9097 .x(FOCUSED_WINDOW_LOCATION.x)
9098 .y(FOCUSED_WINDOW_LOCATION.y))
9099 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009100 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009101 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009102 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009103 // We consumed all events, so no ANR
9104 ASSERT_TRUE(mDispatcher->waitForIdle());
9105 mFakePolicy->assertNotifyAnrWasNotCalled();
9106
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009108 injectMotionEvent(*mDispatcher,
9109 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
9110 AINPUT_SOURCE_TOUCHSCREEN)
9111 .pointer(PointerBuilder(0, ToolType::FINGER)
9112 .x(FOCUSED_WINDOW_LOCATION.x)
9113 .y(FOCUSED_WINDOW_LOCATION.y))
9114 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009115 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009116 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009117
9118 const std::chrono::duration timeout =
9119 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009120 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07009121
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009122 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009123 mFocusedWindow->consumeMotionDown();
9124 // This cancel is generated because the connection was unresponsive
9125 mFocusedWindow->consumeMotionCancel();
9126 mFocusedWindow->assertNoEvents();
9127 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009128 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009129 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9130 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009131 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009132}
9133
9134// If we have 2 windows with identical timeouts that are both unresponsive,
9135// it doesn't matter which order they should have ANR.
9136// But we should receive ANR for both.
9137TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
9138 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009139 mUnfocusedWindow->setDispatchingTimeout(
9140 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009141 mDispatcher->onWindowInfosChanged(
9142 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009143
9144 tapOnFocusedWindow();
9145 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009146 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009147 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
9148 mFocusedWindow->getDispatchingTimeout(
9149 DISPATCHING_TIMEOUT)),
9150 mFakePolicy->getUnresponsiveWindowToken(0ms)};
9151
9152 ASSERT_THAT(anrConnectionTokens,
9153 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9154 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009155
9156 ASSERT_TRUE(mDispatcher->waitForIdle());
9157 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009158
9159 mFocusedWindow->consumeMotionDown();
9160 mFocusedWindow->consumeMotionUp();
9161 mUnfocusedWindow->consumeMotionOutside();
9162
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009163 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
9164 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009165
9166 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009167 ASSERT_THAT(responsiveTokens,
9168 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
9169 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009170 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009171}
9172
9173// If a window is already not responding, the second tap on the same window should be ignored.
9174// We should also log an error to account for the dropped event (not tested here).
9175// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
9176TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
9177 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009178 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009179 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009180 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009181 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009182 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009183 ASSERT_TRUE(upEventSequenceNum);
9184 const std::chrono::duration timeout =
9185 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009186 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009187
9188 // Tap once again
9189 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009190 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009191 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009192 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009193 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009194 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009195 FOCUSED_WINDOW_LOCATION));
9196 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
9197 // valid touch target
9198 mUnfocusedWindow->assertNoEvents();
9199
9200 // Consume the first tap
9201 mFocusedWindow->finishEvent(*downEventSequenceNum);
9202 mFocusedWindow->finishEvent(*upEventSequenceNum);
9203 ASSERT_TRUE(mDispatcher->waitForIdle());
9204 // The second tap did not go to the focused window
9205 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009206 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08009207 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9208 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009209 mFakePolicy->assertNotifyAnrWasNotCalled();
9210}
9211
9212// If you tap outside of all windows, there will not be ANR
9213TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009214 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009215 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009216 LOCATION_OUTSIDE_ALL_WINDOWS));
9217 ASSERT_TRUE(mDispatcher->waitForIdle());
9218 mFakePolicy->assertNotifyAnrWasNotCalled();
9219}
9220
9221// Since the focused window is paused, tapping on it should not produce any events
9222TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
9223 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009224 mDispatcher->onWindowInfosChanged(
9225 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009226
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009227 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009228 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009229 FOCUSED_WINDOW_LOCATION));
9230
9231 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
9232 ASSERT_TRUE(mDispatcher->waitForIdle());
9233 // Should not ANR because the window is paused, and touches shouldn't go to it
9234 mFakePolicy->assertNotifyAnrWasNotCalled();
9235
9236 mFocusedWindow->assertNoEvents();
9237 mUnfocusedWindow->assertNoEvents();
9238}
9239
9240/**
9241 * 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 -07009242 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009243 * If a different window becomes focused at this time, the key should go to that window instead.
9244 *
9245 * Warning!!!
9246 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
9247 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009248 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009249 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
9250 *
9251 * If that value changes, this test should also change.
9252 */
9253TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
9254 // Set a long ANR timeout to prevent it from triggering
9255 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009256 mDispatcher->onWindowInfosChanged(
9257 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009258
9259 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009260 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009261 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009262 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009263 ASSERT_TRUE(upSequenceNum);
9264 // Don't finish the events yet, and send a key
9265 // Injection will succeed because we will eventually give up and send the key to the focused
9266 // window even if motions are still being processed.
9267
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009268 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009269 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9270 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009272 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009273 // and the key remains pending, waiting for the touch events to be processed.
9274 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
9275 // under the hood.
9276 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9277 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009278
9279 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009280 mFocusedWindow->setFocusable(false);
9281 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009282 mDispatcher->onWindowInfosChanged(
9283 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009284 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009285
9286 // Focus events should precede the key events
9287 mUnfocusedWindow->consumeFocusEvent(true);
9288 mFocusedWindow->consumeFocusEvent(false);
9289
9290 // Finish the tap events, which should unblock dispatcher
9291 mUnfocusedWindow->finishEvent(*downSequenceNum);
9292 mUnfocusedWindow->finishEvent(*upSequenceNum);
9293
9294 // Now that all queues are cleared and no backlog in the connections, the key event
9295 // can finally go to the newly focused "mUnfocusedWindow".
9296 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9297 mFocusedWindow->assertNoEvents();
9298 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009299 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009300}
9301
9302// When the touch stream is split across 2 windows, and one of them does not respond,
9303// then ANR should be raised and the touch should be canceled for the unresponsive window.
9304// The other window should not be affected by that.
9305TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9306 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009307 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9308 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9309 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009310 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009311
9312 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009313 mDispatcher->notifyMotion(
9314 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9315 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009316
9317 const std::chrono::duration timeout =
9318 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009319 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009320
9321 mUnfocusedWindow->consumeMotionDown();
9322 mFocusedWindow->consumeMotionDown();
9323 // Focused window may or may not receive ACTION_MOVE
9324 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009325 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009326 ASSERT_TRUE(moveOrCancelSequenceNum);
9327 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9328 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009329 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009330 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9331 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9332 mFocusedWindow->consumeMotionCancel();
9333 } else {
9334 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9335 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009336 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009337 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9338 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009339
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009340 mUnfocusedWindow->assertNoEvents();
9341 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009342 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009343}
9344
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009345/**
9346 * If we have no focused window, and a key comes in, we start the ANR timer.
9347 * The focused application should add a focused window before the timer runs out to prevent ANR.
9348 *
9349 * If the user touches another application during this time, the key should be dropped.
9350 * Next, if a new focused window comes in, without toggling the focused application,
9351 * then no ANR should occur.
9352 *
9353 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9354 * but in some cases the policy may not update the focused application.
9355 */
9356TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9357 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9358 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009359 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009360 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9361 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9362 mFocusedWindow->setFocusable(false);
9363
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009364 mDispatcher->onWindowInfosChanged(
9365 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009366 mFocusedWindow->consumeFocusEvent(false);
9367
9368 // Send a key. The ANR timer should start because there is no focused window.
9369 // 'focusedApplication' will get blamed if this timer completes.
9370 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009371 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009372 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9373 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009374 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009376
9377 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9378 // then the injected touches won't cause the focused event to get dropped.
9379 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9380 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9381 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9382 // For this test, it means that the key would get delivered to the window once it becomes
9383 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009384 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009385
9386 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009387 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9388 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9389 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009390
9391 // We do not consume the motion right away, because that would require dispatcher to first
9392 // process (== drop) the key event, and by that time, ANR will be raised.
9393 // Set the focused window first.
9394 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009395 mDispatcher->onWindowInfosChanged(
9396 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009397 setFocusedWindow(mFocusedWindow);
9398 mFocusedWindow->consumeFocusEvent(true);
9399 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9400 // to another application. This could be a bug / behaviour in the policy.
9401
9402 mUnfocusedWindow->consumeMotionDown();
9403
9404 ASSERT_TRUE(mDispatcher->waitForIdle());
9405 // Should not ANR because we actually have a focused window. It was just added too slowly.
9406 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9407}
9408
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009409/**
9410 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9411 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9412 * dispatcher doesn't prune pointer events incorrectly.
9413 *
9414 * This test reproduces a crash in InputDispatcher.
9415 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9416 *
9417 * Keep the currently focused application (mApplication), and have no focused window.
9418 * We set up two additional windows:
9419 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9420 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9421 * window. This window is not focusable, but is touchable.
9422 *
9423 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9424 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9425 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9426 *
9427 * Now, we touch "Another window". This window is owned by a different application than
9428 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9429 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9430 * dropping the events from its queue. Ensure that no crash occurs.
9431 *
9432 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9433 * This does not affect the test running time.
9434 */
9435TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9436 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9437 std::make_shared<FakeApplicationHandle>();
9438 systemUiApplication->setDispatchingTimeout(3000ms);
9439 mFakePolicy->setStaleEventTimeout(3000ms);
9440 sp<FakeWindowHandle> navigationBar =
9441 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9442 ADISPLAY_ID_DEFAULT);
9443 navigationBar->setFocusable(false);
9444 navigationBar->setWatchOutsideTouch(true);
9445 navigationBar->setFrame(Rect(0, 0, 100, 100));
9446
9447 mApplication->setDispatchingTimeout(3000ms);
9448 // 'mApplication' is already focused, but we call it again here to make it explicit.
9449 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9450
9451 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9452 std::make_shared<FakeApplicationHandle>();
9453 sp<FakeWindowHandle> appWindow =
9454 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9455 ADISPLAY_ID_DEFAULT);
9456 appWindow->setFocusable(false);
9457 appWindow->setFrame(Rect(100, 100, 200, 200));
9458
9459 mDispatcher->onWindowInfosChanged(
9460 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9461 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9462 mFocusedWindow->consumeFocusEvent(false);
9463
9464 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9465 // in response.
9466 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9467 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9468 .build());
9469 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9470
9471 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9472 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9473 InputEventInjectionResult result =
9474 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9475 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9476 /*allowKeyRepeat=*/false);
9477 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9478
9479 // Finish the gesture - lift up finger and inject ACTION_UP key event
9480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9481 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9482 .build());
9483 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9484 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9485 /*allowKeyRepeat=*/false);
9486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9487 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9488 // getting any events yet.
9489 navigationBar->assertNoEvents();
9490
9491 // Now touch "Another window". This touch is going to a different application than the one we
9492 // are waiting for (which is 'mApplication').
9493 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9494 // trying to be injected) and to continue processing the rest of the events in the original
9495 // order.
9496 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9497 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9498 .build());
9499 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9500 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9501 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9502
9503 appWindow->assertNoEvents();
9504 navigationBar->assertNoEvents();
9505}
9506
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009507// These tests ensure we cannot send touch events to a window that's positioned behind a window
9508// that has feature NO_INPUT_CHANNEL.
9509// Layout:
9510// Top (closest to user)
9511// mNoInputWindow (above all windows)
9512// mBottomWindow
9513// Bottom (furthest from user)
9514class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9515 virtual void SetUp() override {
9516 InputDispatcherTest::SetUp();
9517
9518 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009519 mNoInputWindow =
9520 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9521 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009522 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009523 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009524 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9525 // It's perfectly valid for this window to not have an associated input channel
9526
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009527 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9528 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009529 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9530
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009531 mDispatcher->onWindowInfosChanged(
9532 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009533 }
9534
9535protected:
9536 std::shared_ptr<FakeApplicationHandle> mApplication;
9537 sp<FakeWindowHandle> mNoInputWindow;
9538 sp<FakeWindowHandle> mBottomWindow;
9539};
9540
9541TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9542 PointF touchedPoint = {10, 10};
9543
Prabir Pradhan678438e2023-04-13 19:32:51 +00009544 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9545 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9546 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009547
9548 mNoInputWindow->assertNoEvents();
9549 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9550 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9551 // and therefore should prevent mBottomWindow from receiving touches
9552 mBottomWindow->assertNoEvents();
9553}
9554
9555/**
9556 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9557 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9558 */
9559TEST_F(InputDispatcherMultiWindowOcclusionTests,
9560 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009561 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9562 "Window with input channel and NO_INPUT_CHANNEL",
9563 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009564
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009565 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009566 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009567 mDispatcher->onWindowInfosChanged(
9568 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009569
9570 PointF touchedPoint = {10, 10};
9571
Prabir Pradhan678438e2023-04-13 19:32:51 +00009572 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9573 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9574 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009575
9576 mNoInputWindow->assertNoEvents();
9577 mBottomWindow->assertNoEvents();
9578}
9579
Vishnu Nair958da932020-08-21 17:12:37 -07009580class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9581protected:
9582 std::shared_ptr<FakeApplicationHandle> mApp;
9583 sp<FakeWindowHandle> mWindow;
9584 sp<FakeWindowHandle> mMirror;
9585
9586 virtual void SetUp() override {
9587 InputDispatcherTest::SetUp();
9588 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009589 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009590 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009591 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9592 mWindow->setFocusable(true);
9593 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009594 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009595 }
9596};
9597
9598TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9599 // Request focus on a mirrored window
9600 setFocusedWindow(mMirror);
9601
9602 // window gets focused
9603 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009604 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009605 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009606 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9607}
9608
9609// A focused & mirrored window remains focused only if the window and its mirror are both
9610// focusable.
9611TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9612 setFocusedWindow(mMirror);
9613
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009614 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009615 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009617 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009618 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009620 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009621 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9622
9623 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009624 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009625
9626 // window loses focus since one of the windows associated with the token in not focusable
9627 mWindow->consumeFocusEvent(false);
9628
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009629 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009630 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009631 mWindow->assertNoEvents();
9632}
9633
9634// A focused & mirrored window remains focused until the window and its mirror both become
9635// invisible.
9636TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9637 setFocusedWindow(mMirror);
9638
9639 // window gets focused
9640 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009642 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009643 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009645 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009646 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9647
9648 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009649 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009650
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009652 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009653 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009655 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009656 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9657
9658 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009659 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009660
9661 // window loses focus only after all windows associated with the token become invisible.
9662 mWindow->consumeFocusEvent(false);
9663
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009664 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009665 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009666 mWindow->assertNoEvents();
9667}
9668
9669// A focused & mirrored window remains focused until both windows are removed.
9670TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9671 setFocusedWindow(mMirror);
9672
9673 // window gets focused
9674 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009676 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009677 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009679 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009680 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9681
9682 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009683 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009684
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009686 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009687 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009689 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009690 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009691
9692 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009693 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009694 mWindow->consumeFocusEvent(false);
9695
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009696 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009697 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009698 mWindow->assertNoEvents();
9699}
9700
9701// Focus request can be pending until one window becomes visible.
9702TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9703 // Request focus on an invisible mirror.
9704 mWindow->setVisible(false);
9705 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009706 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009707 setFocusedWindow(mMirror);
9708
9709 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009711 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9712 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009713
9714 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009715 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009716
9717 // window gets focused
9718 mWindow->consumeFocusEvent(true);
9719 // window gets the pending key event
9720 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9721}
Prabir Pradhan99987712020-11-10 18:43:05 -08009722
9723class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9724protected:
9725 std::shared_ptr<FakeApplicationHandle> mApp;
9726 sp<FakeWindowHandle> mWindow;
9727 sp<FakeWindowHandle> mSecondWindow;
9728
9729 void SetUp() override {
9730 InputDispatcherTest::SetUp();
9731 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009732 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009733 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009734 mSecondWindow =
9735 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009736 mSecondWindow->setFocusable(true);
9737
9738 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009739 mDispatcher->onWindowInfosChanged(
9740 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009741
9742 setFocusedWindow(mWindow);
9743 mWindow->consumeFocusEvent(true);
9744 }
9745
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009746 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009747 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009748 }
9749
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009750 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9751 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009752 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009753 auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
9754 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009755 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009756 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009757 }
9758};
9759
9760TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9761 // Ensure that capture cannot be obtained for unfocused windows.
9762 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9763 mFakePolicy->assertSetPointerCaptureNotCalled();
9764 mSecondWindow->assertNoEvents();
9765
9766 // Ensure that capture can be enabled from the focus window.
9767 requestAndVerifyPointerCapture(mWindow, true);
9768
9769 // Ensure that capture cannot be disabled from a window that does not have capture.
9770 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9771 mFakePolicy->assertSetPointerCaptureNotCalled();
9772
9773 // Ensure that capture can be disabled from the window with capture.
9774 requestAndVerifyPointerCapture(mWindow, false);
9775}
9776
9777TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009778 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009779
9780 setFocusedWindow(mSecondWindow);
9781
9782 // Ensure that the capture disabled event was sent first.
9783 mWindow->consumeCaptureEvent(false);
9784 mWindow->consumeFocusEvent(false);
9785 mSecondWindow->consumeFocusEvent(true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009786 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009787
9788 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009789 notifyPointerCaptureChanged({});
9790 notifyPointerCaptureChanged(request);
9791 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009792 mWindow->assertNoEvents();
9793 mSecondWindow->assertNoEvents();
9794 mFakePolicy->assertSetPointerCaptureNotCalled();
9795}
9796
9797TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009798 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009799
9800 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009801 notifyPointerCaptureChanged({});
9802 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009803
9804 // Ensure that Pointer Capture is disabled.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009805 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009806 mWindow->consumeCaptureEvent(false);
9807 mWindow->assertNoEvents();
9808}
9809
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009810TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9811 requestAndVerifyPointerCapture(mWindow, true);
9812
9813 // The first window loses focus.
9814 setFocusedWindow(mSecondWindow);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009815 mFakePolicy->assertSetPointerCaptureCalled(false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009816 mWindow->consumeCaptureEvent(false);
9817
9818 // Request Pointer Capture from the second window before the notification from InputReader
9819 // arrives.
9820 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009821 auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009822
9823 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009824 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009825
9826 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009827 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009828
9829 mSecondWindow->consumeFocusEvent(true);
9830 mSecondWindow->consumeCaptureEvent(true);
9831}
9832
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009833TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9834 // App repeatedly enables and disables capture.
9835 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9836 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9837 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9838 mFakePolicy->assertSetPointerCaptureCalled(false);
9839 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9840 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9841
9842 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9843 // first request is now stale, this should do nothing.
9844 notifyPointerCaptureChanged(firstRequest);
9845 mWindow->assertNoEvents();
9846
9847 // InputReader notifies that the second request was enabled.
9848 notifyPointerCaptureChanged(secondRequest);
9849 mWindow->consumeCaptureEvent(true);
9850}
9851
Prabir Pradhan7092e262022-05-03 16:51:09 +00009852TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9853 requestAndVerifyPointerCapture(mWindow, true);
9854
9855 // App toggles pointer capture off and on.
9856 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
9857 mFakePolicy->assertSetPointerCaptureCalled(false);
9858
9859 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9860 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
9861
9862 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9863 // preceding "disable" request.
9864 notifyPointerCaptureChanged(enableRequest);
9865
9866 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9867 // any notifications.
9868 mWindow->assertNoEvents();
9869}
9870
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009871/**
9872 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9873 * mouse movements don't affect the previous mouse hovering state.
9874 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9875 * HOVER_MOVE events).
9876 */
9877TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9878 // Mouse hover on the window
9879 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9880 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9881 .build());
9882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9883 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9884 .build());
9885
9886 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9887 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9888
9889 // Start pointer capture
9890 requestAndVerifyPointerCapture(mWindow, true);
9891
9892 // Send some relative mouse movements and receive them in the window.
9893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9894 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9895 .build());
9896 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9897 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9898
9899 // Stop pointer capture
9900 requestAndVerifyPointerCapture(mWindow, false);
9901
9902 // Continue hovering on the window
9903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9904 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9905 .build());
9906 mWindow->consumeMotionEvent(
9907 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9908
9909 mWindow->assertNoEvents();
9910}
9911
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009912class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9913protected:
9914 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009915
9916 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9917 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9918
9919 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9920 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9921
9922 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9923 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9924 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9925 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9926 MAXIMUM_OBSCURING_OPACITY);
9927
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009928 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9929 static constexpr gui::Uid APP_B_UID{10002};
9930 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009931
9932 sp<FakeWindowHandle> mTouchWindow;
9933
9934 virtual void SetUp() override {
9935 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009936 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009937 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9938 }
9939
9940 virtual void TearDown() override {
9941 InputDispatcherTest::TearDown();
9942 mTouchWindow.clear();
9943 }
9944
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009945 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009946 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009947 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009948 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009949 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009950 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009951 return window;
9952 }
9953
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009954 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009955 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9956 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009957 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009958 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009959 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009960 return window;
9961 }
9962
9963 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009964 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9965 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9966 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009967 }
9968};
9969
9970TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009971 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009972 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009973 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009974
9975 touch();
9976
9977 mTouchWindow->assertNoEvents();
9978}
9979
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009980TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009981 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9982 const sp<FakeWindowHandle>& w =
9983 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009984 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009985
9986 touch();
9987
9988 mTouchWindow->assertNoEvents();
9989}
9990
9991TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009992 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9993 const sp<FakeWindowHandle>& w =
9994 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009995 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009996
9997 touch();
9998
9999 w->assertNoEvents();
10000}
10001
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010002TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010003 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010004 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010005
10006 touch();
10007
10008 mTouchWindow->consumeAnyMotionDown();
10009}
10010
10011TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010012 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010013 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010014 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010015 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010016
10017 touch({PointF{100, 100}});
10018
10019 mTouchWindow->consumeAnyMotionDown();
10020}
10021
10022TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010023 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010024 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010025 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010026
10027 touch();
10028
10029 mTouchWindow->consumeAnyMotionDown();
10030}
10031
10032TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
10033 const sp<FakeWindowHandle>& w =
10034 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010035 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010036
10037 touch();
10038
10039 mTouchWindow->consumeAnyMotionDown();
10040}
10041
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010042TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
10043 const sp<FakeWindowHandle>& w =
10044 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010045 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010046
10047 touch();
10048
10049 w->assertNoEvents();
10050}
10051
10052/**
10053 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
10054 * inside) while letting them pass-through. Note that even though touch passes through the occluding
10055 * window, the occluding window will still receive ACTION_OUTSIDE event.
10056 */
10057TEST_F(InputDispatcherUntrustedTouchesTest,
10058 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
10059 const sp<FakeWindowHandle>& w =
10060 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010061 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010062 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010063
10064 touch();
10065
10066 w->consumeMotionOutside();
10067}
10068
10069TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
10070 const sp<FakeWindowHandle>& w =
10071 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010072 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010073 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010074
10075 touch();
10076
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080010077 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000010078}
10079
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010080TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010081 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010082 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10083 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010084 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010085
10086 touch();
10087
10088 mTouchWindow->consumeAnyMotionDown();
10089}
10090
10091TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
10092 const sp<FakeWindowHandle>& w =
10093 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10094 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010095 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010096
10097 touch();
10098
10099 mTouchWindow->consumeAnyMotionDown();
10100}
10101
10102TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010103 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010104 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10105 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010106 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010107
10108 touch();
10109
10110 mTouchWindow->assertNoEvents();
10111}
10112
10113TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
10114 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
10115 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010116 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10117 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010118 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010119 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10120 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010121 mDispatcher->onWindowInfosChanged(
10122 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010123
10124 touch();
10125
10126 mTouchWindow->assertNoEvents();
10127}
10128
10129TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
10130 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
10131 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010132 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
10133 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010134 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010135 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
10136 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010137 mDispatcher->onWindowInfosChanged(
10138 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010139
10140 touch();
10141
10142 mTouchWindow->consumeAnyMotionDown();
10143}
10144
10145TEST_F(InputDispatcherUntrustedTouchesTest,
10146 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
10147 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010148 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10149 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010150 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010151 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10152 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010153 mDispatcher->onWindowInfosChanged(
10154 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010155
10156 touch();
10157
10158 mTouchWindow->consumeAnyMotionDown();
10159}
10160
10161TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
10162 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010163 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10164 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000010165 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010166 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10167 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010168 mDispatcher->onWindowInfosChanged(
10169 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000010170
10171 touch();
10172
10173 mTouchWindow->assertNoEvents();
10174}
10175
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010176TEST_F(InputDispatcherUntrustedTouchesTest,
10177 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
10178 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010179 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10180 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010181 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010182 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10183 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged(
10185 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010186
10187 touch();
10188
10189 mTouchWindow->assertNoEvents();
10190}
10191
10192TEST_F(InputDispatcherUntrustedTouchesTest,
10193 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
10194 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010195 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10196 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010197 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010198 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10199 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010200 mDispatcher->onWindowInfosChanged(
10201 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010202
10203 touch();
10204
10205 mTouchWindow->consumeAnyMotionDown();
10206}
10207
10208TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
10209 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010210 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
10211 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010212 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010213
10214 touch();
10215
10216 mTouchWindow->consumeAnyMotionDown();
10217}
10218
10219TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
10220 const sp<FakeWindowHandle>& w =
10221 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010222 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000010223
10224 touch();
10225
10226 mTouchWindow->consumeAnyMotionDown();
10227}
10228
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010229TEST_F(InputDispatcherUntrustedTouchesTest,
10230 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
10231 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10232 const sp<FakeWindowHandle>& w =
10233 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010234 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010235
10236 touch();
10237
10238 mTouchWindow->assertNoEvents();
10239}
10240
10241TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
10242 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
10243 const sp<FakeWindowHandle>& w =
10244 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010245 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010246
10247 touch();
10248
10249 mTouchWindow->consumeAnyMotionDown();
10250}
10251
10252TEST_F(InputDispatcherUntrustedTouchesTest,
10253 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
10254 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
10255 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000010256 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10257 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010258 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010259
10260 touch();
10261
10262 mTouchWindow->consumeAnyMotionDown();
10263}
10264
10265TEST_F(InputDispatcherUntrustedTouchesTest,
10266 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10267 const sp<FakeWindowHandle>& w1 =
10268 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10269 OPACITY_BELOW_THRESHOLD);
10270 const sp<FakeWindowHandle>& w2 =
10271 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10272 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010273 mDispatcher->onWindowInfosChanged(
10274 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010275
10276 touch();
10277
10278 mTouchWindow->assertNoEvents();
10279}
10280
10281/**
10282 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10283 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10284 * (which alone would result in allowing touches) does not affect the blocking behavior.
10285 */
10286TEST_F(InputDispatcherUntrustedTouchesTest,
10287 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10288 const sp<FakeWindowHandle>& wB =
10289 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10290 OPACITY_BELOW_THRESHOLD);
10291 const sp<FakeWindowHandle>& wC =
10292 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10293 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010294 mDispatcher->onWindowInfosChanged(
10295 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010296
10297 touch();
10298
10299 mTouchWindow->assertNoEvents();
10300}
10301
10302/**
10303 * This test is testing that a window from a different UID but with same application token doesn't
10304 * block the touch. Apps can share the application token for close UI collaboration for example.
10305 */
10306TEST_F(InputDispatcherUntrustedTouchesTest,
10307 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10308 const sp<FakeWindowHandle>& w =
10309 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10310 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010311 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010312
10313 touch();
10314
10315 mTouchWindow->consumeAnyMotionDown();
10316}
10317
arthurhungb89ccb02020-12-30 16:19:01 +080010318class InputDispatcherDragTests : public InputDispatcherTest {
10319protected:
10320 std::shared_ptr<FakeApplicationHandle> mApp;
10321 sp<FakeWindowHandle> mWindow;
10322 sp<FakeWindowHandle> mSecondWindow;
10323 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010324 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010325 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10326 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010327
10328 void SetUp() override {
10329 InputDispatcherTest::SetUp();
10330 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010331 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010332 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010333
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010334 mSecondWindow =
10335 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010336 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010337
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010338 mSpyWindow =
10339 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010340 mSpyWindow->setSpy(true);
10341 mSpyWindow->setTrustedOverlay(true);
10342 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10343
arthurhungb89ccb02020-12-30 16:19:01 +080010344 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010345 mDispatcher->onWindowInfosChanged(
10346 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10347 {},
10348 0,
10349 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010350 }
10351
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010352 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10353 switch (fromSource) {
10354 case AINPUT_SOURCE_TOUCHSCREEN:
10355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010356 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010357 ADISPLAY_ID_DEFAULT, {50, 50}))
10358 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10359 break;
10360 case AINPUT_SOURCE_STYLUS:
10361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010362 injectMotionEvent(*mDispatcher,
10363 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10364 AINPUT_SOURCE_STYLUS)
10365 .buttonState(
10366 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10367 .pointer(PointerBuilder(0, ToolType::STYLUS)
10368 .x(50)
10369 .y(50))
10370 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010371 break;
10372 case AINPUT_SOURCE_MOUSE:
10373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010374 injectMotionEvent(*mDispatcher,
10375 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10376 AINPUT_SOURCE_MOUSE)
10377 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10378 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10379 ToolType::MOUSE)
10380 .x(50)
10381 .y(50))
10382 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010383 break;
10384 default:
10385 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10386 }
arthurhungb89ccb02020-12-30 16:19:01 +080010387
10388 // Window should receive motion event.
10389 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010390 // Spy window should also receive motion event
10391 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010392 }
10393
10394 // Start performing drag, we will create a drag window and transfer touch to it.
10395 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10396 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010397 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010398 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010399 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010400 }
arthurhungb89ccb02020-12-30 16:19:01 +080010401
10402 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010403 mDragWindow =
10404 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010405 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010406 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10407 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10408 {},
10409 0,
10410 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010411
10412 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010413 bool transferred =
10414 mDispatcher->transferTouchFocus(mWindow->getToken(), mDragWindow->getToken(),
Harry Cutts33476232023-01-30 19:57:29 +000010415 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010416 if (transferred) {
10417 mWindow->consumeMotionCancel();
10418 mDragWindow->consumeMotionDown();
10419 }
10420 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010421 }
10422};
10423
10424TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010425 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010426
10427 // Move on window.
10428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010429 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010430 ADISPLAY_ID_DEFAULT, {50, 50}))
10431 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10432 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10433 mWindow->consumeDragEvent(false, 50, 50);
10434 mSecondWindow->assertNoEvents();
10435
10436 // Move to another window.
10437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010438 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010439 ADISPLAY_ID_DEFAULT, {150, 50}))
10440 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10441 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10442 mWindow->consumeDragEvent(true, 150, 50);
10443 mSecondWindow->consumeDragEvent(false, 50, 50);
10444
10445 // Move back to original window.
10446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010447 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010448 ADISPLAY_ID_DEFAULT, {50, 50}))
10449 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10450 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10451 mWindow->consumeDragEvent(false, 50, 50);
10452 mSecondWindow->consumeDragEvent(true, -50, 50);
10453
10454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010455 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10456 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010457 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10458 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10459 mWindow->assertNoEvents();
10460 mSecondWindow->assertNoEvents();
10461}
10462
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010463TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010464 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010465
10466 // No cancel event after drag start
10467 mSpyWindow->assertNoEvents();
10468
10469 const MotionEvent secondFingerDownEvent =
10470 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10471 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010472 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10473 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010474 .build();
10475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010476 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010477 InputEventInjectionSync::WAIT_FOR_RESULT))
10478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10479
10480 // Receives cancel for first pointer after next pointer down
10481 mSpyWindow->consumeMotionCancel();
10482 mSpyWindow->consumeMotionDown();
10483
10484 mSpyWindow->assertNoEvents();
10485}
10486
arthurhungf452d0b2021-01-06 00:19:52 +080010487TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010488 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010489
10490 // Move on window.
10491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010492 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010493 ADISPLAY_ID_DEFAULT, {50, 50}))
10494 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10495 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10496 mWindow->consumeDragEvent(false, 50, 50);
10497 mSecondWindow->assertNoEvents();
10498
10499 // Move to another window.
10500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010501 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010502 ADISPLAY_ID_DEFAULT, {150, 50}))
10503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10504 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10505 mWindow->consumeDragEvent(true, 150, 50);
10506 mSecondWindow->consumeDragEvent(false, 50, 50);
10507
10508 // drop to another window.
10509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010510 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010511 {150, 50}))
10512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10513 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010514 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010515 mWindow->assertNoEvents();
10516 mSecondWindow->assertNoEvents();
10517}
10518
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010519TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10520 startDrag();
10521
10522 // No cancel event after drag start
10523 mSpyWindow->assertNoEvents();
10524
10525 const MotionEvent secondFingerDownEvent =
10526 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10527 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10528 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10529 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10530 .build();
10531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10532 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10533 InputEventInjectionSync::WAIT_FOR_RESULT))
10534 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10535
10536 // Receives cancel for first pointer after next pointer down
10537 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010538 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010539 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10540
10541 mSpyWindow->assertNoEvents();
10542
10543 // Spy window calls pilfer pointers
10544 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10545 mDragWindow->assertNoEvents();
10546
10547 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010548 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010549 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10550 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10551 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10552 .build();
10553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010554 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010555 InputEventInjectionSync::WAIT_FOR_RESULT))
10556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10557
10558 // Drag window should still receive the new event
10559 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10560 mDragWindow->assertNoEvents();
10561}
10562
arthurhung6d4bed92021-03-17 11:59:33 +080010563TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010564 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010565
10566 // Move on window and keep button pressed.
10567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010568 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010569 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10570 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010572 .build()))
10573 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10574 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10575 mWindow->consumeDragEvent(false, 50, 50);
10576 mSecondWindow->assertNoEvents();
10577
10578 // Move to another window and release button, expect to drop item.
10579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010580 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010581 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10582 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010584 .build()))
10585 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10586 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10587 mWindow->assertNoEvents();
10588 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010589 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010590
10591 // nothing to the window.
10592 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010593 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010594 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10595 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010596 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010597 .build()))
10598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10599 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
10600 mWindow->assertNoEvents();
10601 mSecondWindow->assertNoEvents();
10602}
10603
Arthur Hung54745652022-04-20 07:17:41 +000010604TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010605 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010606
10607 // Set second window invisible.
10608 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010609 mDispatcher->onWindowInfosChanged(
10610 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010611
10612 // Move on window.
10613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010614 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010615 ADISPLAY_ID_DEFAULT, {50, 50}))
10616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10617 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10618 mWindow->consumeDragEvent(false, 50, 50);
10619 mSecondWindow->assertNoEvents();
10620
10621 // Move to another window.
10622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010623 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010624 ADISPLAY_ID_DEFAULT, {150, 50}))
10625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10626 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10627 mWindow->consumeDragEvent(true, 150, 50);
10628 mSecondWindow->assertNoEvents();
10629
10630 // drop to another window.
10631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010632 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010633 {150, 50}))
10634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10635 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010636 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010637 mWindow->assertNoEvents();
10638 mSecondWindow->assertNoEvents();
10639}
10640
Arthur Hung54745652022-04-20 07:17:41 +000010641TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010642 // Ensure window could track pointerIds if it didn't support split touch.
10643 mWindow->setPreventSplitting(true);
10644
Arthur Hung54745652022-04-20 07:17:41 +000010645 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010646 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010647 {50, 50}))
10648 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10649 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10650
10651 const MotionEvent secondFingerDownEvent =
10652 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10653 .displayId(ADISPLAY_ID_DEFAULT)
10654 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010655 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10656 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010657 .build();
10658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010659 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010660 InputEventInjectionSync::WAIT_FOR_RESULT))
10661 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010662 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010663
10664 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010665 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010666}
10667
10668TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10669 // First down on second window.
10670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010671 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010672 {150, 50}))
10673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10674
10675 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10676
10677 // Second down on first window.
10678 const MotionEvent secondFingerDownEvent =
10679 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10680 .displayId(ADISPLAY_ID_DEFAULT)
10681 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010682 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10683 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010684 .build();
10685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010686 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010687 InputEventInjectionSync::WAIT_FOR_RESULT))
10688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10689 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10690
10691 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010692 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010693
10694 // Move on window.
10695 const MotionEvent secondFingerMoveEvent =
10696 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10697 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010698 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10699 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010700 .build();
10701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010702 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010703 InputEventInjectionSync::WAIT_FOR_RESULT));
10704 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10705 mWindow->consumeDragEvent(false, 50, 50);
10706 mSecondWindow->consumeMotionMove();
10707
10708 // Release the drag pointer should perform drop.
10709 const MotionEvent secondFingerUpEvent =
10710 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10711 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010712 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10713 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010714 .build();
10715 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010716 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010717 InputEventInjectionSync::WAIT_FOR_RESULT));
10718 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010719 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010720 mWindow->assertNoEvents();
10721 mSecondWindow->consumeMotionMove();
10722}
10723
Arthur Hung3915c1f2022-05-31 07:17:17 +000010724TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010725 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010726
10727 // Update window of second display.
10728 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010729 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010730 mDispatcher->onWindowInfosChanged(
10731 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10732 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10733 {},
10734 0,
10735 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010736
10737 // Let second display has a touch state.
10738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010739 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010740 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10741 AINPUT_SOURCE_TOUCHSCREEN)
10742 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010743 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010744 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010745 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010746 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010747 mDispatcher->onWindowInfosChanged(
10748 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10749 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10750 {},
10751 0,
10752 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010753
10754 // Move on window.
10755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010756 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010757 ADISPLAY_ID_DEFAULT, {50, 50}))
10758 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10759 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10760 mWindow->consumeDragEvent(false, 50, 50);
10761 mSecondWindow->assertNoEvents();
10762
10763 // Move to another window.
10764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010765 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010766 ADISPLAY_ID_DEFAULT, {150, 50}))
10767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10768 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10769 mWindow->consumeDragEvent(true, 150, 50);
10770 mSecondWindow->consumeDragEvent(false, 50, 50);
10771
10772 // drop to another window.
10773 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010774 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010775 {150, 50}))
10776 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10777 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010778 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010779 mWindow->assertNoEvents();
10780 mSecondWindow->assertNoEvents();
10781}
10782
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010783TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10784 startDrag(true, AINPUT_SOURCE_MOUSE);
10785 // Move on window.
10786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010787 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010788 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10789 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010790 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010791 .x(50)
10792 .y(50))
10793 .build()))
10794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10795 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10796 mWindow->consumeDragEvent(false, 50, 50);
10797 mSecondWindow->assertNoEvents();
10798
10799 // Move to another window.
10800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010801 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010802 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10803 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010804 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010805 .x(150)
10806 .y(50))
10807 .build()))
10808 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10809 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
10810 mWindow->consumeDragEvent(true, 150, 50);
10811 mSecondWindow->consumeDragEvent(false, 50, 50);
10812
10813 // drop to another window.
10814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010815 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010816 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10817 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010818 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010819 .x(150)
10820 .y(50))
10821 .build()))
10822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10823 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010824 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010825 mWindow->assertNoEvents();
10826 mSecondWindow->assertNoEvents();
10827}
10828
Linnan Li5af92f92023-07-14 14:36:22 +080010829/**
10830 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10831 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10832 */
10833TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10834 // Down on second window
10835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10836 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10837 {150, 50}))
10838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10839
10840 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10841 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10842
10843 // Down on first window
10844 const MotionEvent secondFingerDownEvent =
10845 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10846 .displayId(ADISPLAY_ID_DEFAULT)
10847 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10848 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10849 .build();
10850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10851 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10852 InputEventInjectionSync::WAIT_FOR_RESULT))
10853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10854 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10855 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10856 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10857
10858 // Start drag on first window
10859 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10860
10861 // Trigger cancel
10862 mDispatcher->cancelCurrentTouch();
10863 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
10864 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel());
10865 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10866
10867 ASSERT_TRUE(mDispatcher->waitForIdle());
10868 // The D&D finished with nullptr
10869 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10870
10871 // Remove drag window
10872 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10873
10874 // Inject a simple gesture, ensure dispatcher not crashed
10875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10877 PointF{50, 50}))
10878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10879 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10880
10881 const MotionEvent moveEvent =
10882 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10883 .displayId(ADISPLAY_ID_DEFAULT)
10884 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10885 .build();
10886 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10887 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10888 InputEventInjectionSync::WAIT_FOR_RESULT))
10889 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10890 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10891
10892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10893 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10894 {50, 50}))
10895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10896 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10897}
10898
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010899TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10900 // Start hovering over the window.
10901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10902 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10903 ADISPLAY_ID_DEFAULT, {50, 50}));
10904
10905 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10906 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10907
10908 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10909 << "Drag and drop should not work with a hovering pointer";
10910}
10911
Vishnu Nair062a8672021-09-03 16:07:44 -070010912class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10913
10914TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10915 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010916 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10917 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010918 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010919 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10920 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010921 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010922 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010923 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010924
10925 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010926 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010927 window->assertNoEvents();
10928
Prabir Pradhan678438e2023-04-13 19:32:51 +000010929 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10930 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010931 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10932 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010933 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010934 window->assertNoEvents();
10935
10936 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010937 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010938 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010939
Prabir Pradhan678438e2023-04-13 19:32:51 +000010940 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010941 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10942
Prabir Pradhan678438e2023-04-13 19:32:51 +000010943 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10944 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010945 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10946 window->assertNoEvents();
10947}
10948
10949TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10950 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10951 std::make_shared<FakeApplicationHandle>();
10952 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010953 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10954 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010955 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010956 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010957 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010958 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010959 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10960 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010961 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010962 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010963 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10964 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010965 mDispatcher->onWindowInfosChanged(
10966 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010967 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010968 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010969
10970 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010971 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010972 window->assertNoEvents();
10973
Prabir Pradhan678438e2023-04-13 19:32:51 +000010974 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10975 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010976 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10977 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010978 window->assertNoEvents();
10979
10980 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010981 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010982 mDispatcher->onWindowInfosChanged(
10983 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010984
Prabir Pradhan678438e2023-04-13 19:32:51 +000010985 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010986 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10987
Prabir Pradhan678438e2023-04-13 19:32:51 +000010988 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10989 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010990 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10991 window->assertNoEvents();
10992}
10993
10994TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10995 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10996 std::make_shared<FakeApplicationHandle>();
10997 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010998 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10999 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070011000 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011001 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011002 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070011003 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011004 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
11005 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011006 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011007 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070011008 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
11009 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011010 mDispatcher->onWindowInfosChanged(
11011 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011012 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011013 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070011014
11015 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000011016 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011017 window->assertNoEvents();
11018
Prabir Pradhan678438e2023-04-13 19:32:51 +000011019 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11020 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070011021 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
11022 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011023 window->assertNoEvents();
11024
11025 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011026 mDispatcher->onWindowInfosChanged(
11027 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070011028
Prabir Pradhan678438e2023-04-13 19:32:51 +000011029 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011030 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
11031
Prabir Pradhan678438e2023-04-13 19:32:51 +000011032 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
11033 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070011034 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11035 window->assertNoEvents();
11036}
11037
Antonio Kantekf16f2832021-09-28 04:39:20 +000011038class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
11039protected:
11040 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000011041 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011042 sp<FakeWindowHandle> mWindow;
11043 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000011044 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000011045
11046 void SetUp() override {
11047 InputDispatcherTest::SetUp();
11048
11049 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000011050 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011051 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011052 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011053 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011054 mSecondWindow =
11055 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011056 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000011057 mThirdWindow =
11058 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
11059 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
11060 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011061
11062 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011063 mDispatcher->onWindowInfosChanged(
11064 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
11065 {},
11066 0,
11067 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000011068 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011069 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011070
Antonio Kantek15beb512022-06-13 22:35:41 +000011071 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011072 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011073 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070011074 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
11075 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011076 mThirdWindow->assertNoEvents();
11077 }
11078
11079 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
11080 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000011081 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000011082 SECOND_DISPLAY_ID)) {
11083 mWindow->assertNoEvents();
11084 mSecondWindow->assertNoEvents();
11085 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070011086 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000011087 }
11088
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011089 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000011090 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070011091 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
11092 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011093 mWindow->consumeTouchModeEvent(inTouchMode);
11094 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000011095 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000011096 }
11097};
11098
Antonio Kantek26defcf2022-02-08 01:12:27 +000011099TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011100 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000011101 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
11102 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011103 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000011104}
11105
Antonio Kantek26defcf2022-02-08 01:12:27 +000011106TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
11107 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011108 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011109 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011110 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011111 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011112 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070011113 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000011114 mWindow->assertNoEvents();
11115 mSecondWindow->assertNoEvents();
11116}
11117
11118TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
11119 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011120 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011121 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011122 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000011123 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000011124 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000011125}
11126
Antonio Kantekf16f2832021-09-28 04:39:20 +000011127TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080011128 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000011129 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
11130 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011131 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000011132 mWindow->assertNoEvents();
11133 mSecondWindow->assertNoEvents();
11134}
11135
Antonio Kantek15beb512022-06-13 22:35:41 +000011136TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
11137 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
11138 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11139 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011140 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000011141 mWindow->assertNoEvents();
11142 mSecondWindow->assertNoEvents();
11143 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
11144}
11145
Antonio Kantek48710e42022-03-24 14:19:30 -070011146TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
11147 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11149 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070011150 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11151 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
11152
11153 // Then remove focus.
11154 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011155 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070011156
11157 // Assert that caller can switch touch mode by owning one of the last interacted window.
11158 const WindowInfo& windowInfo = *mWindow->getInfo();
11159 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
11160 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000011161 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070011162}
11163
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011164class InputDispatcherSpyWindowTest : public InputDispatcherTest {
11165public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011166 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011167 std::shared_ptr<FakeApplicationHandle> application =
11168 std::make_shared<FakeApplicationHandle>();
11169 std::string name = "Fake Spy ";
11170 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011171 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
11172 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011173 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011174 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011175 return spy;
11176 }
11177
11178 sp<FakeWindowHandle> createForeground() {
11179 std::shared_ptr<FakeApplicationHandle> application =
11180 std::make_shared<FakeApplicationHandle>();
11181 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011182 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
11183 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011184 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011185 return window;
11186 }
11187
11188private:
11189 int mSpyCount{0};
11190};
11191
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011192using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011193/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011194 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
11195 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011196TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070011197 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011198 ScopedSilentDeath _silentDeath;
11199
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011200 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011201 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011202 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080011203 ".* not a trusted overlay");
11204}
11205
11206/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011207 * Input injection into a display with a spy window but no foreground windows should succeed.
11208 */
11209TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011210 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011211 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011212
11213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011214 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011215 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11216 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11217}
11218
11219/**
11220 * Verify the order in which different input windows receive events. The touched foreground window
11221 * (if there is one) should always receive the event first. When there are multiple spy windows, the
11222 * spy windows will receive the event according to their Z-order, where the top-most spy window will
11223 * receive events before ones belows it.
11224 *
11225 * Here, we set up a scenario with four windows in the following Z order from the top:
11226 * spy1, spy2, window, spy3.
11227 * We then inject an event and verify that the foreground "window" receives it first, followed by
11228 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
11229 * window.
11230 */
11231TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
11232 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011233 auto spy1 = createSpy();
11234 auto spy2 = createSpy();
11235 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011236 mDispatcher->onWindowInfosChanged(
11237 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011238 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
11239 const size_t numChannels = channels.size();
11240
Michael Wright8e9a8562022-02-09 13:44:29 +000011241 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011242 if (!epollFd.ok()) {
11243 FAIL() << "Failed to create epoll fd";
11244 }
11245
11246 for (size_t i = 0; i < numChannels; i++) {
11247 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
11248 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
11249 FAIL() << "Failed to add fd to epoll";
11250 }
11251 }
11252
11253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11256
11257 std::vector<size_t> eventOrder;
11258 std::vector<struct epoll_event> events(numChannels);
11259 for (;;) {
11260 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11261 (100ms).count());
11262 if (nFds < 0) {
11263 FAIL() << "Failed to call epoll_wait";
11264 }
11265 if (nFds == 0) {
11266 break; // epoll_wait timed out
11267 }
11268 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011269 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011270 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011271 channels[i]->consumeMotionDown();
11272 }
11273 }
11274
11275 // Verify the order in which the events were received.
11276 EXPECT_EQ(3u, eventOrder.size());
11277 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11278 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11279 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11280}
11281
11282/**
11283 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11284 */
11285TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11286 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011287 auto spy = createSpy();
11288 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011289 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011290
11291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011292 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11294 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11295 spy->assertNoEvents();
11296}
11297
11298/**
11299 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11300 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11301 * to the window.
11302 */
11303TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11304 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011305 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011306 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011307 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011308
11309 // Inject an event outside the spy window's touchable region.
11310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011311 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011312 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11313 window->consumeMotionDown();
11314 spy->assertNoEvents();
11315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011316 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11318 window->consumeMotionUp();
11319 spy->assertNoEvents();
11320
11321 // Inject an event inside the spy window's touchable region.
11322 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011323 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011324 {5, 10}))
11325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11326 window->consumeMotionDown();
11327 spy->consumeMotionDown();
11328}
11329
11330/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011331 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011332 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011333 */
11334TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11335 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011336 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011337 auto spy = createSpy();
11338 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011339 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011340 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011341 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011342
11343 // Inject an event outside the spy window's frame and touchable region.
11344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011345 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011346 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011347 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11348 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011349 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011350}
11351
11352/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011353 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11354 * pointers that are down within its bounds.
11355 */
11356TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11357 auto windowLeft = createForeground();
11358 windowLeft->setFrame({0, 0, 100, 200});
11359 auto windowRight = createForeground();
11360 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011361 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011362 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011363 mDispatcher->onWindowInfosChanged(
11364 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011365
11366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011367 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011368 {50, 50}))
11369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11370 windowLeft->consumeMotionDown();
11371 spy->consumeMotionDown();
11372
11373 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011374 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011375 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011376 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11377 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011378 .build();
11379 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011380 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011381 InputEventInjectionSync::WAIT_FOR_RESULT))
11382 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11383 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011384 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011385}
11386
11387/**
11388 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11389 * the spy should receive the second pointer with ACTION_DOWN.
11390 */
11391TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11392 auto window = createForeground();
11393 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011394 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011395 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011396 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011397
11398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011399 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011400 {50, 50}))
11401 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11402 window->consumeMotionDown();
11403 spyRight->assertNoEvents();
11404
11405 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011406 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011407 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011408 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11409 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011410 .build();
11411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011412 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011413 InputEventInjectionSync::WAIT_FOR_RESULT))
11414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011415 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011416 spyRight->consumeMotionDown();
11417}
11418
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011419/**
11420 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11421 * windows should be allowed to control split touch.
11422 */
11423TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011424 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011425 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011426 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011427 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011428
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011429 auto window = createForeground();
11430 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011432 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011433
11434 // First finger down, no window touched.
11435 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011436 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011437 {100, 200}))
11438 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11439 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11440 window->assertNoEvents();
11441
11442 // Second finger down on window, the window should receive touch down.
11443 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011444 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011445 .displayId(ADISPLAY_ID_DEFAULT)
11446 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011447 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11448 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011449 .build();
11450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011451 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011452 InputEventInjectionSync::WAIT_FOR_RESULT))
11453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11454
11455 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011456 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011457}
11458
11459/**
11460 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11461 * do not receive key events.
11462 */
11463TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011464 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011465 spy->setFocusable(false);
11466
11467 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011468 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011469 setFocusedWindow(window);
11470 window->consumeFocusEvent(true);
11471
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011473 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11474 window->consumeKeyDown(ADISPLAY_ID_NONE);
11475
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011477 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11478 window->consumeKeyUp(ADISPLAY_ID_NONE);
11479
11480 spy->assertNoEvents();
11481}
11482
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011483using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11484
11485/**
11486 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11487 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11488 */
11489TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11490 auto window = createForeground();
11491 auto spy1 = createSpy();
11492 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011493 mDispatcher->onWindowInfosChanged(
11494 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011495
11496 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011497 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011498 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11499 window->consumeMotionDown();
11500 spy1->consumeMotionDown();
11501 spy2->consumeMotionDown();
11502
11503 // Pilfer pointers from the second spy window.
11504 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11505 spy2->assertNoEvents();
11506 spy1->consumeMotionCancel();
11507 window->consumeMotionCancel();
11508
11509 // The rest of the gesture should only be sent to the second spy window.
11510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011511 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011512 ADISPLAY_ID_DEFAULT))
11513 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11514 spy2->consumeMotionMove();
11515 spy1->assertNoEvents();
11516 window->assertNoEvents();
11517}
11518
11519/**
11520 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11521 * in the middle of the gesture.
11522 */
11523TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11524 auto window = createForeground();
11525 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011526 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011527
11528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011529 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011530 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11531 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11532 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11533
11534 window->releaseChannel();
11535
11536 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11537
11538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011539 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11541 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11542}
11543
11544/**
11545 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11546 * the spy, but not to any other windows.
11547 */
11548TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11549 auto spy = createSpy();
11550 auto window = createForeground();
11551
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011552 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011553
11554 // First finger down on the window and the spy.
11555 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011556 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011557 {100, 200}))
11558 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11559 spy->consumeMotionDown();
11560 window->consumeMotionDown();
11561
11562 // Spy window pilfers the pointers.
11563 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11564 window->consumeMotionCancel();
11565
11566 // Second finger down on the window and spy, but the window should not receive the pointer down.
11567 const MotionEvent secondFingerDownEvent =
11568 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11569 .displayId(ADISPLAY_ID_DEFAULT)
11570 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011571 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11572 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011573 .build();
11574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011575 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011576 InputEventInjectionSync::WAIT_FOR_RESULT))
11577 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11578
Harry Cutts33476232023-01-30 19:57:29 +000011579 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011580
11581 // Third finger goes down outside all windows, so injection should fail.
11582 const MotionEvent thirdFingerDownEvent =
11583 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11584 .displayId(ADISPLAY_ID_DEFAULT)
11585 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011586 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11587 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11588 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011589 .build();
11590 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011591 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011592 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011593 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011594
11595 spy->assertNoEvents();
11596 window->assertNoEvents();
11597}
11598
11599/**
11600 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11601 */
11602TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11603 auto spy = createSpy();
11604 spy->setFrame(Rect(0, 0, 100, 100));
11605 auto window = createForeground();
11606 window->setFrame(Rect(0, 0, 200, 200));
11607
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011608 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011609
11610 // First finger down on the window only
11611 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011612 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011613 {150, 150}))
11614 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11615 window->consumeMotionDown();
11616
11617 // Second finger down on the spy and window
11618 const MotionEvent secondFingerDownEvent =
11619 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11620 .displayId(ADISPLAY_ID_DEFAULT)
11621 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011622 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11623 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011624 .build();
11625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011626 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011627 InputEventInjectionSync::WAIT_FOR_RESULT))
11628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11629 spy->consumeMotionDown();
11630 window->consumeMotionPointerDown(1);
11631
11632 // Third finger down on the spy and window
11633 const MotionEvent thirdFingerDownEvent =
11634 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11635 .displayId(ADISPLAY_ID_DEFAULT)
11636 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011637 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11638 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11639 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011640 .build();
11641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011642 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011643 InputEventInjectionSync::WAIT_FOR_RESULT))
11644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11645 spy->consumeMotionPointerDown(1);
11646 window->consumeMotionPointerDown(2);
11647
11648 // Spy window pilfers the pointers.
11649 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011650 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11651 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011652
11653 spy->assertNoEvents();
11654 window->assertNoEvents();
11655}
11656
11657/**
11658 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11659 * other windows should be canceled. If this results in the cancellation of all pointers for some
11660 * window, then that window should receive ACTION_CANCEL.
11661 */
11662TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11663 auto spy = createSpy();
11664 spy->setFrame(Rect(0, 0, 100, 100));
11665 auto window = createForeground();
11666 window->setFrame(Rect(0, 0, 200, 200));
11667
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 // First finger down on both spy and window
11671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011672 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011673 {10, 10}))
11674 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11675 window->consumeMotionDown();
11676 spy->consumeMotionDown();
11677
11678 // Second finger down on the spy and window
11679 const MotionEvent secondFingerDownEvent =
11680 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11681 .displayId(ADISPLAY_ID_DEFAULT)
11682 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011683 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11684 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011685 .build();
11686 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011687 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011688 InputEventInjectionSync::WAIT_FOR_RESULT))
11689 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11690 spy->consumeMotionPointerDown(1);
11691 window->consumeMotionPointerDown(1);
11692
11693 // Spy window pilfers the pointers.
11694 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11695 window->consumeMotionCancel();
11696
11697 spy->assertNoEvents();
11698 window->assertNoEvents();
11699}
11700
11701/**
11702 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11703 * be sent to other windows
11704 */
11705TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11706 auto spy = createSpy();
11707 spy->setFrame(Rect(0, 0, 100, 100));
11708 auto window = createForeground();
11709 window->setFrame(Rect(0, 0, 200, 200));
11710
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011711 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011712
11713 // First finger down on both window and spy
11714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011716 {10, 10}))
11717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11718 window->consumeMotionDown();
11719 spy->consumeMotionDown();
11720
11721 // Spy window pilfers the pointers.
11722 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11723 window->consumeMotionCancel();
11724
11725 // Second finger down on the window only
11726 const MotionEvent secondFingerDownEvent =
11727 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11728 .displayId(ADISPLAY_ID_DEFAULT)
11729 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011730 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11731 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011732 .build();
11733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011734 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011735 InputEventInjectionSync::WAIT_FOR_RESULT))
11736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11737 window->consumeMotionDown();
11738 window->assertNoEvents();
11739
11740 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11741 spy->consumeMotionMove();
11742 spy->assertNoEvents();
11743}
11744
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011745/**
11746 * A window on the left and a window on the right. Also, a spy window that's above all of the
11747 * windows, and spanning both left and right windows.
11748 * Send simultaneous motion streams from two different devices, one to the left window, and another
11749 * to the right window.
11750 * Pilfer from spy window.
11751 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11752 */
11753TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11754 sp<FakeWindowHandle> spy = createSpy();
11755 spy->setFrame(Rect(0, 0, 200, 200));
11756 sp<FakeWindowHandle> leftWindow = createForeground();
11757 leftWindow->setFrame(Rect(0, 0, 100, 100));
11758
11759 sp<FakeWindowHandle> rightWindow = createForeground();
11760 rightWindow->setFrame(Rect(100, 0, 200, 100));
11761
11762 constexpr int32_t stylusDeviceId = 1;
11763 constexpr int32_t touchDeviceId = 2;
11764
11765 mDispatcher->onWindowInfosChanged(
11766 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11767
11768 // Stylus down on left window and spy
11769 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11770 .deviceId(stylusDeviceId)
11771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11772 .build());
11773 leftWindow->consumeMotionEvent(
11774 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11775 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11776
11777 // Finger down on right window and spy - but spy already has stylus
11778 mDispatcher->notifyMotion(
11779 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11780 .deviceId(touchDeviceId)
11781 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11782 .build());
11783 rightWindow->consumeMotionEvent(
11784 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011785 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011786
11787 // Act: pilfer from spy. Spy is currently receiving touch events.
11788 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011789 leftWindow->consumeMotionEvent(
11790 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011791 rightWindow->consumeMotionEvent(
11792 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11793
11794 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11795 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11796 .deviceId(stylusDeviceId)
11797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11798 .build());
11799 mDispatcher->notifyMotion(
11800 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11801 .deviceId(touchDeviceId)
11802 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11803 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011804 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011805
11806 spy->assertNoEvents();
11807 leftWindow->assertNoEvents();
11808 rightWindow->assertNoEvents();
11809}
11810
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011811TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11812 auto window = createForeground();
11813 auto spy = createSpy();
11814 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11815
11816 mDispatcher->notifyMotion(
11817 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11818 .deviceId(1)
11819 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11820 .build());
11821 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11822 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11823
11824 // Pilfer pointers from the spy window should fail.
11825 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11826 spy->assertNoEvents();
11827 window->assertNoEvents();
11828}
11829
Prabir Pradhand65552b2021-10-07 11:23:50 -070011830class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11831public:
11832 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11833 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11834 std::make_shared<FakeApplicationHandle>();
11835 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011836 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11837 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011838 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011839 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011840 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011841 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011842 overlay->setTrustedOverlay(true);
11843
11844 std::shared_ptr<FakeApplicationHandle> application =
11845 std::make_shared<FakeApplicationHandle>();
11846 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011847 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11848 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011849 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011850 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011851
11852 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011853 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011854 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011855 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011856 return {std::move(overlay), std::move(window)};
11857 }
11858
11859 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011860 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011861 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011862 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011863 }
11864
11865 void sendStylusEvent(int32_t action) {
11866 NotifyMotionArgs motionArgs =
11867 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11868 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011869 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011870 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011871 }
11872};
11873
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011874using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11875
11876TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011877 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011878 ScopedSilentDeath _silentDeath;
11879
Prabir Pradhand65552b2021-10-07 11:23:50 -070011880 auto [overlay, window] = setupStylusOverlayScenario();
11881 overlay->setTrustedOverlay(false);
11882 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011883 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11884 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011885 ".* not a trusted overlay");
11886}
11887
11888TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11889 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011890 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011891
11892 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11893 overlay->consumeMotionDown();
11894 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11895 overlay->consumeMotionUp();
11896
11897 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11898 window->consumeMotionDown();
11899 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11900 window->consumeMotionUp();
11901
11902 overlay->assertNoEvents();
11903 window->assertNoEvents();
11904}
11905
11906TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11907 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011908 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011909 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011910
11911 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11912 overlay->consumeMotionDown();
11913 window->consumeMotionDown();
11914 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11915 overlay->consumeMotionUp();
11916 window->consumeMotionUp();
11917
11918 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11919 window->consumeMotionDown();
11920 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11921 window->consumeMotionUp();
11922
11923 overlay->assertNoEvents();
11924 window->assertNoEvents();
11925}
11926
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011927/**
11928 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11929 * The scenario is as follows:
11930 * - The stylus interceptor overlay is configured as a spy window.
11931 * - The stylus interceptor spy receives the start of a new stylus gesture.
11932 * - It pilfers pointers and then configures itself to no longer be a spy.
11933 * - The stylus interceptor continues to receive the rest of the gesture.
11934 */
11935TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11936 auto [overlay, window] = setupStylusOverlayScenario();
11937 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011938 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011939
11940 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11941 overlay->consumeMotionDown();
11942 window->consumeMotionDown();
11943
11944 // The interceptor pilfers the pointers.
11945 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11946 window->consumeMotionCancel();
11947
11948 // The interceptor configures itself so that it is no longer a spy.
11949 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011950 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011951
11952 // It continues to receive the rest of the stylus gesture.
11953 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11954 overlay->consumeMotionMove();
11955 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11956 overlay->consumeMotionUp();
11957
11958 window->assertNoEvents();
11959}
11960
Prabir Pradhan5735a322022-04-11 17:23:34 +000011961struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011962 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011963 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011964 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11965 std::unique_ptr<InputDispatcher>& mDispatcher;
11966
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011967 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011968 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11969
11970 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011971 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011972 ADISPLAY_ID_DEFAULT, {100, 200},
11973 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11974 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11975 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11976 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11977 }
11978
11979 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011980 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011981 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011982 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011983 mPolicyFlags);
11984 }
11985
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011986 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011987 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11988 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011989 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11990 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011991 window->setOwnerInfo(mPid, mUid);
11992 return window;
11993 }
11994};
11995
11996using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11997
11998TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011999 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012000 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012001 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012002
12003 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12004 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12005 window->consumeMotionDown();
12006
12007 setFocusedWindow(window);
12008 window->consumeFocusEvent(true);
12009
12010 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12011 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12012 window->consumeKeyDown(ADISPLAY_ID_NONE);
12013}
12014
12015TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012016 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012017 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012018 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012019
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012020 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012021 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12022 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12023
12024 setFocusedWindow(window);
12025 window->consumeFocusEvent(true);
12026
12027 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
12028 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
12029 window->assertNoEvents();
12030}
12031
12032TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012033 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012034 auto window = owner.createWindow("Owned window");
12035 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012036 spy->setSpy(true);
12037 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012038 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012039
12040 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12041 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12042 spy->consumeMotionDown();
12043 window->consumeMotionDown();
12044}
12045
12046TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012047 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012048 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012049
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012050 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012051 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012052 randosSpy->setSpy(true);
12053 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012054 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012055
12056 // The event is targeted at owner's window, so injection should succeed, but the spy should
12057 // not receive the event.
12058 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12059 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12060 randosSpy->assertNoEvents();
12061 window->consumeMotionDown();
12062}
12063
12064TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012065 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012066 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012067
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012068 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012069 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012070 randosSpy->setSpy(true);
12071 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012072 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012073
12074 // A user that has injection permission can inject into any window.
12075 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012076 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000012077 ADISPLAY_ID_DEFAULT));
12078 randosSpy->consumeMotionDown();
12079 window->consumeMotionDown();
12080
12081 setFocusedWindow(randosSpy);
12082 randosSpy->consumeFocusEvent(true);
12083
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012084 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000012085 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
12086 window->assertNoEvents();
12087}
12088
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012089TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012090 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012091 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012092
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012093 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070012094 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000012095 randosWindow->setFrame(Rect{-10, -10, -5, -5});
12096 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012097 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000012098
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012099 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012100 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
12101 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
12102 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070012103 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000012104}
12105
Prabir Pradhan64f21d22023-11-28 21:19:42 +000012106using InputDispatcherPointerInWindowTest = InputDispatcherTest;
12107
12108TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
12109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12110
12111 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12112 ADISPLAY_ID_DEFAULT);
12113 left->setFrame(Rect(0, 0, 100, 100));
12114 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12115 "Right Window", ADISPLAY_ID_DEFAULT);
12116 right->setFrame(Rect(100, 0, 200, 100));
12117 sp<FakeWindowHandle> spy =
12118 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12119 spy->setFrame(Rect(0, 0, 200, 100));
12120 spy->setTrustedOverlay(true);
12121 spy->setSpy(true);
12122
12123 mDispatcher->onWindowInfosChanged(
12124 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12125
12126 // Hover into the left window.
12127 mDispatcher->notifyMotion(
12128 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
12129 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
12130 .build());
12131
12132 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12133 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12134
12135 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12136 /*pointerId=*/0));
12137 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12138 /*pointerId=*/0));
12139 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12140 /*pointerId=*/0));
12141
12142 // Hover move to the right window.
12143 mDispatcher->notifyMotion(
12144 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
12145 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12146 .build());
12147
12148 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12149 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12150 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
12151
12152 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12153 /*pointerId=*/0));
12154 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12155 /*pointerId=*/0));
12156 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12157 /*pointerId=*/0));
12158
12159 // Stop hovering.
12160 mDispatcher->notifyMotion(
12161 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
12162 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
12163 .build());
12164
12165 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12166 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12167
12168 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12169 /*pointerId=*/0));
12170 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12171 /*pointerId=*/0));
12172 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12173 /*pointerId=*/0));
12174}
12175
12176TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
12177 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12178
12179 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12180 ADISPLAY_ID_DEFAULT);
12181 left->setFrame(Rect(0, 0, 100, 100));
12182 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12183 "Right Window", ADISPLAY_ID_DEFAULT);
12184 right->setFrame(Rect(100, 0, 200, 100));
12185 sp<FakeWindowHandle> spy =
12186 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
12187 spy->setFrame(Rect(0, 0, 200, 100));
12188 spy->setTrustedOverlay(true);
12189 spy->setSpy(true);
12190
12191 mDispatcher->onWindowInfosChanged(
12192 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
12193
12194 // First pointer down on left window.
12195 mDispatcher->notifyMotion(
12196 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12197 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12198 .build());
12199
12200 left->consumeMotionDown();
12201 spy->consumeMotionDown();
12202
12203 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12204 /*pointerId=*/0));
12205 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12206 /*pointerId=*/0));
12207 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12208 /*pointerId=*/0));
12209
12210 // Second pointer down on right window.
12211 mDispatcher->notifyMotion(
12212 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12213 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12214 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12215 .build());
12216
12217 left->consumeMotionMove();
12218 right->consumeMotionDown();
12219 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
12220
12221 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12222 /*pointerId=*/0));
12223 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12224 /*pointerId=*/0));
12225 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12226 /*pointerId=*/0));
12227 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12228 /*pointerId=*/1));
12229 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12230 /*pointerId=*/1));
12231 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12232 /*pointerId=*/1));
12233
12234 // Second pointer up.
12235 mDispatcher->notifyMotion(
12236 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12237 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12238 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
12239 .build());
12240
12241 left->consumeMotionMove();
12242 right->consumeMotionUp();
12243 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
12244
12245 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12246 /*pointerId=*/0));
12247 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12248 /*pointerId=*/0));
12249 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12250 /*pointerId=*/0));
12251 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12252 /*pointerId=*/1));
12253 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12254 /*pointerId=*/1));
12255 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12256 /*pointerId=*/1));
12257
12258 // First pointer up.
12259 mDispatcher->notifyMotion(
12260 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12261 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12262 .build());
12263
12264 left->consumeMotionUp();
12265 spy->consumeMotionUp();
12266
12267 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12268 /*pointerId=*/0));
12269 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12270 /*pointerId=*/0));
12271 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12272 /*pointerId=*/0));
12273}
12274
12275TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12277
12278 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12279 ADISPLAY_ID_DEFAULT);
12280 left->setFrame(Rect(0, 0, 100, 100));
12281 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12282 "Right Window", ADISPLAY_ID_DEFAULT);
12283 right->setFrame(Rect(100, 0, 200, 100));
12284
12285 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12286
12287 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12288 /*pointerId=*/0));
12289 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12290 /*pointerId=*/0));
12291
12292 // Hover move into the window.
12293 mDispatcher->notifyMotion(
12294 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12295 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12296 .rawXCursorPosition(50)
12297 .rawYCursorPosition(50)
12298 .deviceId(DEVICE_ID)
12299 .build());
12300
12301 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12302
12303 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12304 /*pointerId=*/0));
12305
12306 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12307 mDispatcher->notifyMotion(
12308 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12309 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12310 .rawXCursorPosition(51)
12311 .rawYCursorPosition(50)
12312 .deviceId(SECOND_DEVICE_ID)
12313 .build());
12314
12315 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12316 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12317
12318 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12319 // a HOVER_EXIT from the first device.
12320 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12321 /*pointerId=*/0));
12322 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12323 SECOND_DEVICE_ID,
12324 /*pointerId=*/0));
12325
12326 // Move the mouse outside the window. Document the current behavior, where the window does not
12327 // receive HOVER_EXIT even though the mouse left the window.
12328 mDispatcher->notifyMotion(
12329 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12330 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12331 .rawXCursorPosition(150)
12332 .rawYCursorPosition(50)
12333 .deviceId(SECOND_DEVICE_ID)
12334 .build());
12335
12336 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12337 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12338 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12339 /*pointerId=*/0));
12340 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12341 SECOND_DEVICE_ID,
12342 /*pointerId=*/0));
12343}
12344
Garfield Tane84e6f92019-08-29 17:28:41 -070012345} // namespace android::inputdispatcher